aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-10-30 03:35:33 -0400
committerIngo Molnar <mingo@kernel.org>2012-10-30 03:35:33 -0400
commit8748dd9b998f06f7cf3a7ffdca27f05bc4835075 (patch)
treed480571278f5952b3f22e43ebb6c75cd0416db5a /tools
parent9db55064940db1447976945d07402a923e818962 (diff)
parent0da2e9c24804d787cbc919b3e0d28ee7c00240ff (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements, fixes and code move from Arnaldo Carvalho de Melo: * Initialize 'page_size' variable in the python binding, this was sent for perf/urgent by mistake, then when merging Ingo removed it, fixing the problem for perf/urgent, but when perf/urgent was merged with perf/core, where that initialization is needed, made the python binding mmap call to fail, fix it by initializing page_size again. * Add a browser for 'perf script' and make it available from the report and annotate browsers. It does filtering to find the scripts that handle events found in the perf.data file used. From Feng Tang * Move some functions from symbol.c to more appropriate files, creating dso.[ch] in the process, no code changes. From Jiri Olsa * Fix mmap error output message for when perf_mmap fails and returns !-EPERM, where the default for mmap_pages, INT_MAX, was causing a !power of 2 error message, fix from Jiri Olsa. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Makefile6
-rw-r--r--tools/perf/builtin-annotate.c5
-rw-r--r--tools/perf/builtin-buildid-cache.c1
-rw-r--r--tools/perf/builtin-buildid-list.c6
-rw-r--r--tools/perf/builtin-evlist.c5
-rw-r--r--tools/perf/builtin-kmem.c5
-rw-r--r--tools/perf/builtin-lock.c2
-rw-r--r--tools/perf/builtin-record.c3
-rw-r--r--tools/perf/builtin-report.c13
-rw-r--r--tools/perf/builtin-sched.c5
-rw-r--r--tools/perf/builtin-script.c83
-rw-r--r--tools/perf/builtin-timechart.c5
-rw-r--r--tools/perf/perf.c1
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/ui/browsers/annotate.c6
-rw-r--r--tools/perf/ui/browsers/hists.c38
-rw-r--r--tools/perf/ui/browsers/scripts.c189
-rw-r--r--tools/perf/util/annotate.c1
-rw-r--r--tools/perf/util/build-id.c15
-rw-r--r--tools/perf/util/build-id.h7
-rw-r--r--tools/perf/util/dso.c594
-rw-r--r--tools/perf/util/dso.h148
-rw-r--r--tools/perf/util/event.h3
-rw-r--r--tools/perf/util/header.c11
-rw-r--r--tools/perf/util/header.h1
-rw-r--r--tools/perf/util/hist.h7
-rw-r--r--tools/perf/util/map.c1
-rw-r--r--tools/perf/util/parse-events.c10
-rw-r--r--tools/perf/util/python.c2
-rw-r--r--tools/perf/util/string.c18
-rw-r--r--tools/perf/util/symbol.c657
-rw-r--r--tools/perf/util/symbol.h141
-rw-r--r--tools/perf/util/util.c33
-rw-r--r--tools/perf/util/util.h2
34 files changed, 1196 insertions, 829 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 629fc6a4b0df..7e25f59e5e89 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -327,6 +327,7 @@ LIB_H += util/svghelper.h
327LIB_H += util/tool.h 327LIB_H += util/tool.h
328LIB_H += util/run-command.h 328LIB_H += util/run-command.h
329LIB_H += util/sigchain.h 329LIB_H += util/sigchain.h
330LIB_H += util/dso.h
330LIB_H += util/symbol.h 331LIB_H += util/symbol.h
331LIB_H += util/color.h 332LIB_H += util/color.h
332LIB_H += util/values.h 333LIB_H += util/values.h
@@ -385,6 +386,7 @@ LIB_OBJS += $(OUTPUT)util/top.o
385LIB_OBJS += $(OUTPUT)util/usage.o 386LIB_OBJS += $(OUTPUT)util/usage.o
386LIB_OBJS += $(OUTPUT)util/wrapper.o 387LIB_OBJS += $(OUTPUT)util/wrapper.o
387LIB_OBJS += $(OUTPUT)util/sigchain.o 388LIB_OBJS += $(OUTPUT)util/sigchain.o
389LIB_OBJS += $(OUTPUT)util/dso.o
388LIB_OBJS += $(OUTPUT)util/symbol.o 390LIB_OBJS += $(OUTPUT)util/symbol.o
389LIB_OBJS += $(OUTPUT)util/symbol-elf.o 391LIB_OBJS += $(OUTPUT)util/symbol-elf.o
390LIB_OBJS += $(OUTPUT)util/dso-test-data.o 392LIB_OBJS += $(OUTPUT)util/dso-test-data.o
@@ -591,6 +593,7 @@ ifndef NO_NEWT
591 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o 593 LIB_OBJS += $(OUTPUT)ui/browsers/annotate.o
592 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o 594 LIB_OBJS += $(OUTPUT)ui/browsers/hists.o
593 LIB_OBJS += $(OUTPUT)ui/browsers/map.o 595 LIB_OBJS += $(OUTPUT)ui/browsers/map.o
596 LIB_OBJS += $(OUTPUT)ui/browsers/scripts.o
594 LIB_OBJS += $(OUTPUT)ui/progress.o 597 LIB_OBJS += $(OUTPUT)ui/progress.o
595 LIB_OBJS += $(OUTPUT)ui/util.o 598 LIB_OBJS += $(OUTPUT)ui/util.o
596 LIB_OBJS += $(OUTPUT)ui/tui/setup.o 599 LIB_OBJS += $(OUTPUT)ui/tui/setup.o
@@ -907,6 +910,9 @@ $(OUTPUT)ui/browsers/hists.o: ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
907$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS 910$(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
908 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $< 911 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
909 912
913$(OUTPUT)ui/browsers/scripts.o: ui/browsers/scripts.c $(OUTPUT)PERF-CFLAGS
914 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
915
910$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 916$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
911 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 917 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-unused-parameter -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
912 918
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index c4bb6457b19e..cb234765ce3d 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -34,7 +34,6 @@
34 34
35struct perf_annotate { 35struct perf_annotate {
36 struct perf_tool tool; 36 struct perf_tool tool;
37 char const *input_name;
38 bool force, use_tui, use_stdio; 37 bool force, use_tui, use_stdio;
39 bool full_paths; 38 bool full_paths;
40 bool print_line; 39 bool print_line;
@@ -175,7 +174,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
175 struct perf_evsel *pos; 174 struct perf_evsel *pos;
176 u64 total_nr_samples; 175 u64 total_nr_samples;
177 176
178 session = perf_session__new(ann->input_name, O_RDONLY, 177 session = perf_session__new(input_name, O_RDONLY,
179 ann->force, false, &ann->tool); 178 ann->force, false, &ann->tool);
180 if (session == NULL) 179 if (session == NULL)
181 return -ENOMEM; 180 return -ENOMEM;
@@ -260,7 +259,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
260 }, 259 },
261 }; 260 };
262 const struct option options[] = { 261 const struct option options[] = {
263 OPT_STRING('i', "input", &annotate.input_name, "file", 262 OPT_STRING('i', "input", &input_name, "file",
264 "input file name"), 263 "input file name"),
265 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]", 264 OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
266 "only consider symbols in these dsos"), 265 "only consider symbols in these dsos"),
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index d37e077f4b14..fae8b250b2ca 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -13,6 +13,7 @@
13#include "util/header.h" 13#include "util/header.h"
14#include "util/parse-options.h" 14#include "util/parse-options.h"
15#include "util/strlist.h" 15#include "util/strlist.h"
16#include "util/build-id.h"
16#include "util/symbol.h" 17#include "util/symbol.h"
17 18
18static int build_id_cache__add_file(const char *filename, const char *debugdir) 19static int build_id_cache__add_file(const char *filename, const char *debugdir)
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index a0e94fffa03e..a82d99fec83e 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -44,8 +44,7 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
44 return fprintf(fp, "%s\n", sbuild_id); 44 return fprintf(fp, "%s\n", sbuild_id);
45} 45}
46 46
47static int perf_session__list_build_ids(const char *input_name, 47static int perf_session__list_build_ids(bool force, bool with_hits)
48 bool force, bool with_hits)
49{ 48{
50 struct perf_session *session; 49 struct perf_session *session;
51 50
@@ -81,7 +80,6 @@ int cmd_buildid_list(int argc, const char **argv,
81 bool show_kernel = false; 80 bool show_kernel = false;
82 bool with_hits = false; 81 bool with_hits = false;
83 bool force = false; 82 bool force = false;
84 const char *input_name = NULL;
85 const struct option options[] = { 83 const struct option options[] = {
86 OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"), 84 OPT_BOOLEAN('H', "with-hits", &with_hits, "Show only DSOs with hits"),
87 OPT_STRING('i', "input", &input_name, "file", "input file name"), 85 OPT_STRING('i', "input", &input_name, "file", "input file name"),
@@ -101,5 +99,5 @@ int cmd_buildid_list(int argc, const char **argv,
101 if (show_kernel) 99 if (show_kernel)
102 return sysfs__fprintf_build_id(stdout); 100 return sysfs__fprintf_build_id(stdout);
103 101
104 return perf_session__list_build_ids(input_name, force, with_hits); 102 return perf_session__list_build_ids(force, with_hits);
105} 103}
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 997afb82691b..c20f1dcfb7e2 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -48,12 +48,12 @@ static int __if_print(bool *first, const char *field, u64 value)
48 48
49#define if_print(field) __if_print(&first, #field, pos->attr.field) 49#define if_print(field) __if_print(&first, #field, pos->attr.field)
50 50
51static int __cmd_evlist(const char *input_name, struct perf_attr_details *details) 51static int __cmd_evlist(const char *file_name, struct perf_attr_details *details)
52{ 52{
53 struct perf_session *session; 53 struct perf_session *session;
54 struct perf_evsel *pos; 54 struct perf_evsel *pos;
55 55
56 session = perf_session__new(input_name, O_RDONLY, 0, false, NULL); 56 session = perf_session__new(file_name, O_RDONLY, 0, false, NULL);
57 if (session == NULL) 57 if (session == NULL)
58 return -ENOMEM; 58 return -ENOMEM;
59 59
@@ -111,7 +111,6 @@ static int __cmd_evlist(const char *input_name, struct perf_attr_details *detail
111int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused) 111int cmd_evlist(int argc, const char **argv, const char *prefix __maybe_unused)
112{ 112{
113 struct perf_attr_details details = { .verbose = false, }; 113 struct perf_attr_details details = { .verbose = false, };
114 const char *input_name = NULL;
115 const struct option options[] = { 114 const struct option options[] = {
116 OPT_STRING('i', "input", &input_name, "file", "Input file name"), 115 OPT_STRING('i', "input", &input_name, "file", "Input file name"),
117 OPT_BOOLEAN('F', "freq", &details.freq, "Show the sample frequency"), 116 OPT_BOOLEAN('F', "freq", &details.freq, "Show the sample frequency"),
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 14bf82f63659..0b4b796167be 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -477,7 +477,7 @@ static void sort_result(void)
477 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort); 477 __sort_result(&root_caller_stat, &root_caller_sorted, &caller_sort);
478} 478}
479 479
480static int __cmd_kmem(const char *input_name) 480static int __cmd_kmem(void)
481{ 481{
482 int err = -EINVAL; 482 int err = -EINVAL;
483 struct perf_session *session; 483 struct perf_session *session;
@@ -743,7 +743,6 @@ static int __cmd_record(int argc, const char **argv)
743int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused) 743int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
744{ 744{
745 const char * const default_sort_order = "frag,hit,bytes"; 745 const char * const default_sort_order = "frag,hit,bytes";
746 const char *input_name = NULL;
747 const struct option kmem_options[] = { 746 const struct option kmem_options[] = {
748 OPT_STRING('i', "input", &input_name, "file", "input file name"), 747 OPT_STRING('i', "input", &input_name, "file", "input file name"),
749 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL, 748 OPT_CALLBACK_NOOPT(0, "caller", NULL, NULL,
@@ -779,7 +778,7 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
779 if (list_empty(&alloc_sort)) 778 if (list_empty(&alloc_sort))
780 setup_sorting(&alloc_sort, default_sort_order); 779 setup_sorting(&alloc_sort, default_sort_order);
781 780
782 return __cmd_kmem(input_name); 781 return __cmd_kmem();
783 } else 782 } else
784 usage_with_options(kmem_usage, kmem_options); 783 usage_with_options(kmem_usage, kmem_options);
785 784
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 6f5f328157aa..425830069749 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -335,8 +335,6 @@ alloc_failed:
335 return NULL; 335 return NULL;
336} 336}
337 337
338static const char *input_name;
339
340struct trace_lock_handler { 338struct trace_lock_handler {
341 int (*acquire_event)(struct perf_evsel *evsel, 339 int (*acquire_event)(struct perf_evsel *evsel,
342 struct perf_sample *sample); 340 struct perf_sample *sample);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 53c9892e96dd..5783c3225116 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -363,7 +363,8 @@ try_again:
363 "or try again with a smaller value of -m/--mmap_pages.\n" 363 "or try again with a smaller value of -m/--mmap_pages.\n"
364 "(current value: %d)\n", opts->mmap_pages); 364 "(current value: %d)\n", opts->mmap_pages);
365 rc = -errno; 365 rc = -errno;
366 } else if (!is_power_of_2(opts->mmap_pages)) { 366 } else if (!is_power_of_2(opts->mmap_pages) &&
367 (opts->mmap_pages != UINT_MAX)) {
367 pr_err("--mmap_pages/-m value must be a power of two."); 368 pr_err("--mmap_pages/-m value must be a power of two.");
368 rc = -EINVAL; 369 rc = -EINVAL;
369 } else { 370 } else {
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 90d1162bb8b8..f07eae73e692 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -40,7 +40,6 @@
40struct perf_report { 40struct perf_report {
41 struct perf_tool tool; 41 struct perf_tool tool;
42 struct perf_session *session; 42 struct perf_session *session;
43 char const *input_name;
44 bool force, use_tui, use_gtk, use_stdio; 43 bool force, use_tui, use_gtk, use_stdio;
45 bool hide_unresolved; 44 bool hide_unresolved;
46 bool dont_use_callchains; 45 bool dont_use_callchains;
@@ -571,7 +570,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
571 .pretty_printing_style = "normal", 570 .pretty_printing_style = "normal",
572 }; 571 };
573 const struct option options[] = { 572 const struct option options[] = {
574 OPT_STRING('i', "input", &report.input_name, "file", 573 OPT_STRING('i', "input", &input_name, "file",
575 "input file name"), 574 "input file name"),
576 OPT_INCR('v', "verbose", &verbose, 575 OPT_INCR('v', "verbose", &verbose,
577 "be more verbose (show symbol address, etc)"), 576 "be more verbose (show symbol address, etc)"),
@@ -657,13 +656,13 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
657 if (report.inverted_callchain) 656 if (report.inverted_callchain)
658 callchain_param.order = ORDER_CALLER; 657 callchain_param.order = ORDER_CALLER;
659 658
660 if (!report.input_name || !strlen(report.input_name)) { 659 if (!input_name || !strlen(input_name)) {
661 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode)) 660 if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
662 report.input_name = "-"; 661 input_name = "-";
663 else 662 else
664 report.input_name = "perf.data"; 663 input_name = "perf.data";
665 } 664 }
666 session = perf_session__new(report.input_name, O_RDONLY, 665 session = perf_session__new(input_name, O_RDONLY,
667 report.force, false, &report.tool); 666 report.force, false, &report.tool);
668 if (session == NULL) 667 if (session == NULL)
669 return -ENOMEM; 668 return -ENOMEM;
@@ -694,7 +693,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
694 693
695 } 694 }
696 695
697 if (strcmp(report.input_name, "-") != 0) 696 if (strcmp(input_name, "-") != 0)
698 setup_browser(true); 697 setup_browser(true);
699 else { 698 else {
700 use_browser = 0; 699 use_browser = 0;
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 30e53360d3c2..cc28b85dabd5 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -120,7 +120,6 @@ struct trace_sched_handler {
120 120
121struct perf_sched { 121struct perf_sched {
122 struct perf_tool tool; 122 struct perf_tool tool;
123 const char *input_name;
124 const char *sort_order; 123 const char *sort_order;
125 unsigned long nr_tasks; 124 unsigned long nr_tasks;
126 struct task_desc *pid_to_task[MAX_PID]; 125 struct task_desc *pid_to_task[MAX_PID];
@@ -1460,7 +1459,7 @@ static int perf_sched__read_events(struct perf_sched *sched, bool destroy,
1460 }; 1459 };
1461 struct perf_session *session; 1460 struct perf_session *session;
1462 1461
1463 session = perf_session__new(sched->input_name, O_RDONLY, 0, false, &sched->tool); 1462 session = perf_session__new(input_name, O_RDONLY, 0, false, &sched->tool);
1464 if (session == NULL) { 1463 if (session == NULL) {
1465 pr_debug("No Memory for session\n"); 1464 pr_debug("No Memory for session\n");
1466 return -1; 1465 return -1;
@@ -1708,7 +1707,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1708 OPT_END() 1707 OPT_END()
1709 }; 1708 };
1710 const struct option sched_options[] = { 1709 const struct option sched_options[] = {
1711 OPT_STRING('i', "input", &sched.input_name, "file", 1710 OPT_STRING('i', "input", &input_name, "file",
1712 "input file name"), 1711 "input file name"),
1713 OPT_INCR('v', "verbose", &verbose, 1712 OPT_INCR('v', "verbose", &verbose,
1714 "be more verbose (show symbol address, etc)"), 1713 "be more verbose (show symbol address, etc)"),
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 04ceb0779d39..b363e7b292b2 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -1030,6 +1030,68 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
1030} 1030}
1031 1031
1032/* 1032/*
1033 * Some scripts specify the required events in their "xxx-record" file,
1034 * this function will check if the events in perf.data match those
1035 * mentioned in the "xxx-record".
1036 *
1037 * Fixme: All existing "xxx-record" are all in good formats "-e event ",
1038 * which is covered well now. And new parsing code should be added to
1039 * cover the future complexing formats like event groups etc.
1040 */
1041static int check_ev_match(char *dir_name, char *scriptname,
1042 struct perf_session *session)
1043{
1044 char filename[MAXPATHLEN], evname[128];
1045 char line[BUFSIZ], *p;
1046 struct perf_evsel *pos;
1047 int match, len;
1048 FILE *fp;
1049
1050 sprintf(filename, "%s/bin/%s-record", dir_name, scriptname);
1051
1052 fp = fopen(filename, "r");
1053 if (!fp)
1054 return -1;
1055
1056 while (fgets(line, sizeof(line), fp)) {
1057 p = ltrim(line);
1058 if (*p == '#')
1059 continue;
1060
1061 while (strlen(p)) {
1062 p = strstr(p, "-e");
1063 if (!p)
1064 break;
1065
1066 p += 2;
1067 p = ltrim(p);
1068 len = strcspn(p, " \t");
1069 if (!len)
1070 break;
1071
1072 snprintf(evname, len + 1, "%s", p);
1073
1074 match = 0;
1075 list_for_each_entry(pos,
1076 &session->evlist->entries, node) {
1077 if (!strcmp(perf_evsel__name(pos), evname)) {
1078 match = 1;
1079 break;
1080 }
1081 }
1082
1083 if (!match) {
1084 fclose(fp);
1085 return -1;
1086 }
1087 }
1088 }
1089
1090 fclose(fp);
1091 return 0;
1092}
1093
1094/*
1033 * Return -1 if none is found, otherwise the actual scripts number. 1095 * Return -1 if none is found, otherwise the actual scripts number.
1034 * 1096 *
1035 * Currently the only user of this function is the script browser, which 1097 * Currently the only user of this function is the script browser, which
@@ -1039,17 +1101,23 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
1039int find_scripts(char **scripts_array, char **scripts_path_array) 1101int find_scripts(char **scripts_array, char **scripts_path_array)
1040{ 1102{
1041 struct dirent *script_next, *lang_next, script_dirent, lang_dirent; 1103 struct dirent *script_next, *lang_next, script_dirent, lang_dirent;
1042 char scripts_path[MAXPATHLEN]; 1104 char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
1043 DIR *scripts_dir, *lang_dir; 1105 DIR *scripts_dir, *lang_dir;
1044 char lang_path[MAXPATHLEN]; 1106 struct perf_session *session;
1045 char *temp; 1107 char *temp;
1046 int i = 0; 1108 int i = 0;
1047 1109
1110 session = perf_session__new(input_name, O_RDONLY, 0, false, NULL);
1111 if (!session)
1112 return -1;
1113
1048 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path()); 1114 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", perf_exec_path());
1049 1115
1050 scripts_dir = opendir(scripts_path); 1116 scripts_dir = opendir(scripts_path);
1051 if (!scripts_dir) 1117 if (!scripts_dir) {
1118 perf_session__delete(session);
1052 return -1; 1119 return -1;
1120 }
1053 1121
1054 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) { 1122 for_each_lang(scripts_path, scripts_dir, lang_dirent, lang_next) {
1055 snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path, 1123 snprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,
@@ -1077,10 +1145,18 @@ int find_scripts(char **scripts_array, char **scripts_path_array)
1077 snprintf(scripts_array[i], 1145 snprintf(scripts_array[i],
1078 (temp - script_dirent.d_name) + 1, 1146 (temp - script_dirent.d_name) + 1,
1079 "%s", script_dirent.d_name); 1147 "%s", script_dirent.d_name);
1148
1149 if (check_ev_match(lang_path,
1150 scripts_array[i], session))
1151 continue;
1152
1080 i++; 1153 i++;
1081 } 1154 }
1155 closedir(lang_dir);
1082 } 1156 }
1083 1157
1158 closedir(scripts_dir);
1159 perf_session__delete(session);
1084 return i; 1160 return i;
1085} 1161}
1086 1162
@@ -1175,7 +1251,6 @@ static int have_cmd(int argc, const char **argv)
1175int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) 1251int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1176{ 1252{
1177 bool show_full_info = false; 1253 bool show_full_info = false;
1178 const char *input_name = NULL;
1179 char *rec_script_path = NULL; 1254 char *rec_script_path = NULL;
1180 char *rep_script_path = NULL; 1255 char *rep_script_path = NULL;
1181 struct perf_session *session; 1256 struct perf_session *session;
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index f251b613b2f3..ab4cf232b852 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -965,7 +965,7 @@ static void write_svg_file(const char *filename)
965 svg_close(); 965 svg_close();
966} 966}
967 967
968static int __cmd_timechart(const char *input_name, const char *output_name) 968static int __cmd_timechart(const char *output_name)
969{ 969{
970 struct perf_tool perf_timechart = { 970 struct perf_tool perf_timechart = {
971 .comm = process_comm_event, 971 .comm = process_comm_event,
@@ -1061,7 +1061,6 @@ parse_process(const struct option *opt __maybe_unused, const char *arg,
1061int cmd_timechart(int argc, const char **argv, 1061int cmd_timechart(int argc, const char **argv,
1062 const char *prefix __maybe_unused) 1062 const char *prefix __maybe_unused)
1063{ 1063{
1064 const char *input_name;
1065 const char *output_name = "output.svg"; 1064 const char *output_name = "output.svg";
1066 const struct option options[] = { 1065 const struct option options[] = {
1067 OPT_STRING('i', "input", &input_name, "file", "input file name"), 1066 OPT_STRING('i', "input", &input_name, "file", "input file name"),
@@ -1092,5 +1091,5 @@ int cmd_timechart(int argc, const char **argv,
1092 1091
1093 setup_pager(); 1092 setup_pager();
1094 1093
1095 return __cmd_timechart(input_name, output_name); 1094 return __cmd_timechart(output_name);
1096} 1095}
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index d480d8a412b8..e9683738d89f 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -24,6 +24,7 @@ const char perf_more_info_string[] =
24 24
25int use_browser = -1; 25int use_browser = -1;
26static int use_pager = -1; 26static int use_pager = -1;
27const char *input_name;
27 28
28struct cmd_struct { 29struct cmd_struct {
29 const char *cmd; 30 const char *cmd;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index c50985eaec41..469fbf2daea4 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -208,6 +208,7 @@ struct branch_stack {
208 struct branch_entry entries[0]; 208 struct branch_entry entries[0];
209}; 209};
210 210
211extern const char *input_name;
211extern bool perf_host, perf_guest; 212extern bool perf_host, perf_guest;
212extern const char perf_version_string[]; 213extern const char perf_version_string[];
213 214
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 8f8cd2d73b3b..28f8aab73aee 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -676,8 +676,14 @@ static int annotate_browser__run(struct annotate_browser *browser, int evidx,
676 "o Toggle disassembler output/simplified view\n" 676 "o Toggle disassembler output/simplified view\n"
677 "s Toggle source code view\n" 677 "s Toggle source code view\n"
678 "/ Search string\n" 678 "/ Search string\n"
679 "r Run available scripts\n"
679 "? Search previous string\n"); 680 "? Search previous string\n");
680 continue; 681 continue;
682 case 'r':
683 {
684 script_browse(NULL);
685 continue;
686 }
681 case 'H': 687 case 'H':
682 nd = browser->curr_hot; 688 nd = browser->curr_hot;
683 break; 689 break;
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index ef2f93ca7496..fe622845872e 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1141,6 +1141,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1141 int nr_options = 0; 1141 int nr_options = 0;
1142 int key = -1; 1142 int key = -1;
1143 char buf[64]; 1143 char buf[64];
1144 char script_opt[64];
1144 1145
1145 if (browser == NULL) 1146 if (browser == NULL)
1146 return -1; 1147 return -1;
@@ -1159,6 +1160,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1159 int choice = 0, 1160 int choice = 0,
1160 annotate = -2, zoom_dso = -2, zoom_thread = -2, 1161 annotate = -2, zoom_dso = -2, zoom_thread = -2,
1161 annotate_f = -2, annotate_t = -2, browse_map = -2; 1162 annotate_f = -2, annotate_t = -2, browse_map = -2;
1163 int scripts_comm = -2, scripts_symbol = -2, scripts_all = -2;
1162 1164
1163 nr_options = 0; 1165 nr_options = 0;
1164 1166
@@ -1211,6 +1213,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1211 hist_browser__reset(browser); 1213 hist_browser__reset(browser);
1212 } 1214 }
1213 continue; 1215 continue;
1216 case 'r':
1217 goto do_scripts;
1214 case K_F1: 1218 case K_F1:
1215 case 'h': 1219 case 'h':
1216 case '?': 1220 case '?':
@@ -1229,6 +1233,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1229 "E Expand all callchains\n" 1233 "E Expand all callchains\n"
1230 "d Zoom into current DSO\n" 1234 "d Zoom into current DSO\n"
1231 "t Zoom into current Thread\n" 1235 "t Zoom into current Thread\n"
1236 "r Run available scripts\n"
1232 "P Print histograms to perf.hist.N\n" 1237 "P Print histograms to perf.hist.N\n"
1233 "V Verbose (DSO names in callchains, etc)\n" 1238 "V Verbose (DSO names in callchains, etc)\n"
1234 "/ Filter symbol by name"); 1239 "/ Filter symbol by name");
@@ -1317,6 +1322,25 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
1317 browser->selection->map != NULL && 1322 browser->selection->map != NULL &&
1318 asprintf(&options[nr_options], "Browse map details") > 0) 1323 asprintf(&options[nr_options], "Browse map details") > 0)
1319 browse_map = nr_options++; 1324 browse_map = nr_options++;
1325
1326 /* perf script support */
1327 if (browser->he_selection) {
1328 struct symbol *sym;
1329
1330 if (asprintf(&options[nr_options], "Run scripts for samples of thread [%s]",
1331 browser->he_selection->thread->comm) > 0)
1332 scripts_comm = nr_options++;
1333
1334 sym = browser->he_selection->ms.sym;
1335 if (sym && sym->namelen &&
1336 asprintf(&options[nr_options], "Run scripts for samples of symbol [%s]",
1337 sym->name) > 0)
1338 scripts_symbol = nr_options++;
1339 }
1340
1341 if (asprintf(&options[nr_options], "Run scripts for all samples") > 0)
1342 scripts_all = nr_options++;
1343
1320add_exit_option: 1344add_exit_option:
1321 options[nr_options++] = (char *)"Exit"; 1345 options[nr_options++] = (char *)"Exit";
1322retry_popup_menu: 1346retry_popup_menu:
@@ -1411,6 +1435,20 @@ zoom_out_thread:
1411 hists__filter_by_thread(hists); 1435 hists__filter_by_thread(hists);
1412 hist_browser__reset(browser); 1436 hist_browser__reset(browser);
1413 } 1437 }
1438 /* perf scripts support */
1439 else if (choice == scripts_all || choice == scripts_comm ||
1440 choice == scripts_symbol) {
1441do_scripts:
1442 memset(script_opt, 0, 64);
1443
1444 if (choice == scripts_comm)
1445 sprintf(script_opt, " -c %s ", browser->he_selection->thread->comm);
1446
1447 if (choice == scripts_symbol)
1448 sprintf(script_opt, " -S %s ", browser->he_selection->ms.sym->name);
1449
1450 script_browse(script_opt);
1451 }
1414 } 1452 }
1415out_free_stack: 1453out_free_stack:
1416 pstack__delete(fstack); 1454 pstack__delete(fstack);
diff --git a/tools/perf/ui/browsers/scripts.c b/tools/perf/ui/browsers/scripts.c
new file mode 100644
index 000000000000..cbbd44b0d93e
--- /dev/null
+++ b/tools/perf/ui/browsers/scripts.c
@@ -0,0 +1,189 @@
1#include <elf.h>
2#include <newt.h>
3#include <inttypes.h>
4#include <sys/ttydefaults.h>
5#include <string.h>
6#include "../../util/sort.h"
7#include "../../util/util.h"
8#include "../../util/hist.h"
9#include "../../util/debug.h"
10#include "../../util/symbol.h"
11#include "../browser.h"
12#include "../helpline.h"
13#include "../libslang.h"
14
15/* 2048 lines should be enough for a script output */
16#define MAX_LINES 2048
17
18/* 160 bytes for one output line */
19#define AVERAGE_LINE_LEN 160
20
21struct script_line {
22 struct list_head node;
23 char line[AVERAGE_LINE_LEN];
24};
25
26struct perf_script_browser {
27 struct ui_browser b;
28 struct list_head entries;
29 const char *script_name;
30 int nr_lines;
31};
32
33#define SCRIPT_NAMELEN 128
34#define SCRIPT_MAX_NO 64
35/*
36 * Usually the full path for a script is:
37 * /home/username/libexec/perf-core/scripts/python/xxx.py
38 * /home/username/libexec/perf-core/scripts/perl/xxx.pl
39 * So 256 should be long enough to contain the full path.
40 */
41#define SCRIPT_FULLPATH_LEN 256
42
43/*
44 * When success, will copy the full path of the selected script
45 * into the buffer pointed by script_name, and return 0.
46 * Return -1 on failure.
47 */
48static int list_scripts(char *script_name)
49{
50 char *buf, *names[SCRIPT_MAX_NO], *paths[SCRIPT_MAX_NO];
51 int i, num, choice, ret = -1;
52
53 /* Preset the script name to SCRIPT_NAMELEN */
54 buf = malloc(SCRIPT_MAX_NO * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN));
55 if (!buf)
56 return ret;
57
58 for (i = 0; i < SCRIPT_MAX_NO; i++) {
59 names[i] = buf + i * (SCRIPT_NAMELEN + SCRIPT_FULLPATH_LEN);
60 paths[i] = names[i] + SCRIPT_NAMELEN;
61 }
62
63 num = find_scripts(names, paths);
64 if (num > 0) {
65 choice = ui__popup_menu(num, names);
66 if (choice < num && choice >= 0) {
67 strcpy(script_name, paths[choice]);
68 ret = 0;
69 }
70 }
71
72 free(buf);
73 return ret;
74}
75
76static void script_browser__write(struct ui_browser *browser,
77 void *entry, int row)
78{
79 struct script_line *sline = list_entry(entry, struct script_line, node);
80 bool current_entry = ui_browser__is_current_entry(browser, row);
81
82 ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
83 HE_COLORSET_NORMAL);
84
85 slsmg_write_nstring(sline->line, browser->width);
86}
87
88static int script_browser__run(struct perf_script_browser *self)
89{
90 int key;
91
92 if (ui_browser__show(&self->b, self->script_name,
93 "Press <- or ESC to exit") < 0)
94 return -1;
95
96 while (1) {
97 key = ui_browser__run(&self->b, 0);
98
99 /* We can add some special key handling here if needed */
100 break;
101 }
102
103 ui_browser__hide(&self->b);
104 return key;
105}
106
107
108int script_browse(const char *script_opt)
109{
110 char cmd[SCRIPT_FULLPATH_LEN*2], script_name[SCRIPT_FULLPATH_LEN];
111 char *line = NULL;
112 size_t len = 0;
113 ssize_t retlen;
114 int ret = -1, nr_entries = 0;
115 FILE *fp;
116 void *buf;
117 struct script_line *sline;
118
119 struct perf_script_browser script = {
120 .b = {
121 .refresh = ui_browser__list_head_refresh,
122 .seek = ui_browser__list_head_seek,
123 .write = script_browser__write,
124 },
125 .script_name = script_name,
126 };
127
128 INIT_LIST_HEAD(&script.entries);
129
130 /* Save each line of the output in one struct script_line object. */
131 buf = zalloc((sizeof(*sline)) * MAX_LINES);
132 if (!buf)
133 return -1;
134 sline = buf;
135
136 memset(script_name, 0, SCRIPT_FULLPATH_LEN);
137 if (list_scripts(script_name))
138 goto exit;
139
140 sprintf(cmd, "perf script -s %s ", script_name);
141
142 if (script_opt)
143 strcat(cmd, script_opt);
144
145 if (input_name) {
146 strcat(cmd, " -i ");
147 strcat(cmd, input_name);
148 }
149
150 strcat(cmd, " 2>&1");
151
152 fp = popen(cmd, "r");
153 if (!fp)
154 goto exit;
155
156 while ((retlen = getline(&line, &len, fp)) != -1) {
157 strncpy(sline->line, line, AVERAGE_LINE_LEN);
158
159 /* If one output line is very large, just cut it short */
160 if (retlen >= AVERAGE_LINE_LEN) {
161 sline->line[AVERAGE_LINE_LEN - 1] = '\0';
162 sline->line[AVERAGE_LINE_LEN - 2] = '\n';
163 }
164 list_add_tail(&sline->node, &script.entries);
165
166 if (script.b.width < retlen)
167 script.b.width = retlen;
168
169 if (nr_entries++ >= MAX_LINES - 1)
170 break;
171 sline++;
172 }
173
174 if (script.b.width > AVERAGE_LINE_LEN)
175 script.b.width = AVERAGE_LINE_LEN;
176
177 if (line)
178 free(line);
179 pclose(fp);
180
181 script.nr_lines = nr_entries;
182 script.b.nr_entries = nr_entries;
183 script.b.entries = &script.entries;
184
185 ret = script_browser__run(&script);
186exit:
187 free(buf);
188 return ret;
189}
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index f0a910371377..7a34dd18b74c 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -15,6 +15,7 @@
15#include "debug.h" 15#include "debug.h"
16#include "annotate.h" 16#include "annotate.h"
17#include <pthread.h> 17#include <pthread.h>
18#include <linux/bitops.h>
18 19
19const char *disassembler_style; 20const char *disassembler_style;
20const char *objdump_path; 21const char *objdump_path;
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 94ca117b8d6e..5295625c0c00 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -70,6 +70,21 @@ struct perf_tool build_id__mark_dso_hit_ops = {
70 .build_id = perf_event__process_build_id, 70 .build_id = perf_event__process_build_id,
71}; 71};
72 72
73int build_id__sprintf(const u8 *build_id, int len, char *bf)
74{
75 char *bid = bf;
76 const u8 *raw = build_id;
77 int i;
78
79 for (i = 0; i < len; ++i) {
80 sprintf(bid, "%02x", *raw);
81 ++raw;
82 bid += 2;
83 }
84
85 return raw - build_id;
86}
87
73char *dso__build_id_filename(struct dso *self, char *bf, size_t size) 88char *dso__build_id_filename(struct dso *self, char *bf, size_t size)
74{ 89{
75 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 90 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 45c500bd5b9f..a811f5c62e18 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -1,10 +1,15 @@
1#ifndef PERF_BUILD_ID_H_ 1#ifndef PERF_BUILD_ID_H_
2#define PERF_BUILD_ID_H_ 1 2#define PERF_BUILD_ID_H_ 1
3 3
4#include "session.h" 4#define BUILD_ID_SIZE 20
5
6#include "tool.h"
7#include "types.h"
5 8
6extern struct perf_tool build_id__mark_dso_hit_ops; 9extern struct perf_tool build_id__mark_dso_hit_ops;
10struct dso;
7 11
12int build_id__sprintf(const u8 *build_id, int len, char *bf);
8char *dso__build_id_filename(struct dso *self, char *bf, size_t size); 13char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
9 14
10int 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,
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
new file mode 100644
index 000000000000..db24a3f0c820
--- /dev/null
+++ b/tools/perf/util/dso.c
@@ -0,0 +1,594 @@
1#include "symbol.h"
2#include "dso.h"
3#include "util.h"
4#include "debug.h"
5
6char dso__symtab_origin(const struct dso *dso)
7{
8 static const char origin[] = {
9 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
10 [DSO_BINARY_TYPE__VMLINUX] = 'v',
11 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
12 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
13 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
14 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
15 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
16 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
17 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
18 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
19 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
20 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
21 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
22 };
23
24 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
25 return '!';
26 return origin[dso->symtab_type];
27}
28
29int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
30 char *root_dir, char *file, size_t size)
31{
32 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
33 int ret = 0;
34
35 switch (type) {
36 case DSO_BINARY_TYPE__DEBUGLINK: {
37 char *debuglink;
38
39 strncpy(file, dso->long_name, size);
40 debuglink = file + dso->long_name_len;
41 while (debuglink != file && *debuglink != '/')
42 debuglink--;
43 if (*debuglink == '/')
44 debuglink++;
45 filename__read_debuglink(dso->long_name, debuglink,
46 size - (debuglink - file));
47 }
48 break;
49 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
50 /* skip the locally configured cache if a symfs is given */
51 if (symbol_conf.symfs[0] ||
52 (dso__build_id_filename(dso, file, size) == NULL))
53 ret = -1;
54 break;
55
56 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
57 snprintf(file, size, "%s/usr/lib/debug%s.debug",
58 symbol_conf.symfs, dso->long_name);
59 break;
60
61 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
62 snprintf(file, size, "%s/usr/lib/debug%s",
63 symbol_conf.symfs, dso->long_name);
64 break;
65
66 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
67 if (!dso->has_build_id) {
68 ret = -1;
69 break;
70 }
71
72 build_id__sprintf(dso->build_id,
73 sizeof(dso->build_id),
74 build_id_hex);
75 snprintf(file, size,
76 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
77 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
78 break;
79
80 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
81 snprintf(file, size, "%s%s",
82 symbol_conf.symfs, dso->long_name);
83 break;
84
85 case DSO_BINARY_TYPE__GUEST_KMODULE:
86 snprintf(file, size, "%s%s%s", symbol_conf.symfs,
87 root_dir, dso->long_name);
88 break;
89
90 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
91 snprintf(file, size, "%s%s", symbol_conf.symfs,
92 dso->long_name);
93 break;
94
95 default:
96 case DSO_BINARY_TYPE__KALLSYMS:
97 case DSO_BINARY_TYPE__VMLINUX:
98 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
99 case DSO_BINARY_TYPE__GUEST_VMLINUX:
100 case DSO_BINARY_TYPE__JAVA_JIT:
101 case DSO_BINARY_TYPE__NOT_FOUND:
102 ret = -1;
103 break;
104 }
105
106 return ret;
107}
108
109static int open_dso(struct dso *dso, struct machine *machine)
110{
111 char *root_dir = (char *) "";
112 char *name;
113 int fd;
114
115 name = malloc(PATH_MAX);
116 if (!name)
117 return -ENOMEM;
118
119 if (machine)
120 root_dir = machine->root_dir;
121
122 if (dso__binary_type_file(dso, dso->data_type,
123 root_dir, name, PATH_MAX)) {
124 free(name);
125 return -EINVAL;
126 }
127
128 fd = open(name, O_RDONLY);
129 free(name);
130 return fd;
131}
132
133int dso__data_fd(struct dso *dso, struct machine *machine)
134{
135 static enum dso_binary_type binary_type_data[] = {
136 DSO_BINARY_TYPE__BUILD_ID_CACHE,
137 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
138 DSO_BINARY_TYPE__NOT_FOUND,
139 };
140 int i = 0;
141
142 if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND)
143 return open_dso(dso, machine);
144
145 do {
146 int fd;
147
148 dso->data_type = binary_type_data[i++];
149
150 fd = open_dso(dso, machine);
151 if (fd >= 0)
152 return fd;
153
154 } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND);
155
156 return -EINVAL;
157}
158
159static void
160dso_cache__free(struct rb_root *root)
161{
162 struct rb_node *next = rb_first(root);
163
164 while (next) {
165 struct dso_cache *cache;
166
167 cache = rb_entry(next, struct dso_cache, rb_node);
168 next = rb_next(&cache->rb_node);
169 rb_erase(&cache->rb_node, root);
170 free(cache);
171 }
172}
173
174static struct dso_cache*
175dso_cache__find(struct rb_root *root, u64 offset)
176{
177 struct rb_node **p = &root->rb_node;
178 struct rb_node *parent = NULL;
179 struct dso_cache *cache;
180
181 while (*p != NULL) {
182 u64 end;
183
184 parent = *p;
185 cache = rb_entry(parent, struct dso_cache, rb_node);
186 end = cache->offset + DSO__DATA_CACHE_SIZE;
187
188 if (offset < cache->offset)
189 p = &(*p)->rb_left;
190 else if (offset >= end)
191 p = &(*p)->rb_right;
192 else
193 return cache;
194 }
195 return NULL;
196}
197
198static void
199dso_cache__insert(struct rb_root *root, struct dso_cache *new)
200{
201 struct rb_node **p = &root->rb_node;
202 struct rb_node *parent = NULL;
203 struct dso_cache *cache;
204 u64 offset = new->offset;
205
206 while (*p != NULL) {
207 u64 end;
208
209 parent = *p;
210 cache = rb_entry(parent, struct dso_cache, rb_node);
211 end = cache->offset + DSO__DATA_CACHE_SIZE;
212
213 if (offset < cache->offset)
214 p = &(*p)->rb_left;
215 else if (offset >= end)
216 p = &(*p)->rb_right;
217 }
218
219 rb_link_node(&new->rb_node, parent, p);
220 rb_insert_color(&new->rb_node, root);
221}
222
223static ssize_t
224dso_cache__memcpy(struct dso_cache *cache, u64 offset,
225 u8 *data, u64 size)
226{
227 u64 cache_offset = offset - cache->offset;
228 u64 cache_size = min(cache->size - cache_offset, size);
229
230 memcpy(data, cache->data + cache_offset, cache_size);
231 return cache_size;
232}
233
234static ssize_t
235dso_cache__read(struct dso *dso, struct machine *machine,
236 u64 offset, u8 *data, ssize_t size)
237{
238 struct dso_cache *cache;
239 ssize_t ret;
240 int fd;
241
242 fd = dso__data_fd(dso, machine);
243 if (fd < 0)
244 return -1;
245
246 do {
247 u64 cache_offset;
248
249 ret = -ENOMEM;
250
251 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
252 if (!cache)
253 break;
254
255 cache_offset = offset & DSO__DATA_CACHE_MASK;
256 ret = -EINVAL;
257
258 if (-1 == lseek(fd, cache_offset, SEEK_SET))
259 break;
260
261 ret = read(fd, cache->data, DSO__DATA_CACHE_SIZE);
262 if (ret <= 0)
263 break;
264
265 cache->offset = cache_offset;
266 cache->size = ret;
267 dso_cache__insert(&dso->cache, cache);
268
269 ret = dso_cache__memcpy(cache, offset, data, size);
270
271 } while (0);
272
273 if (ret <= 0)
274 free(cache);
275
276 close(fd);
277 return ret;
278}
279
280static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
281 u64 offset, u8 *data, ssize_t size)
282{
283 struct dso_cache *cache;
284
285 cache = dso_cache__find(&dso->cache, offset);
286 if (cache)
287 return dso_cache__memcpy(cache, offset, data, size);
288 else
289 return dso_cache__read(dso, machine, offset, data, size);
290}
291
292ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
293 u64 offset, u8 *data, ssize_t size)
294{
295 ssize_t r = 0;
296 u8 *p = data;
297
298 do {
299 ssize_t ret;
300
301 ret = dso_cache_read(dso, machine, offset, p, size);
302 if (ret < 0)
303 return ret;
304
305 /* Reached EOF, return what we have. */
306 if (!ret)
307 break;
308
309 BUG_ON(ret > size);
310
311 r += ret;
312 p += ret;
313 offset += ret;
314 size -= ret;
315
316 } while (size);
317
318 return r;
319}
320
321ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
322 struct machine *machine, u64 addr,
323 u8 *data, ssize_t size)
324{
325 u64 offset = map->map_ip(map, addr);
326 return dso__data_read_offset(dso, machine, offset, data, size);
327}
328
329struct map *dso__new_map(const char *name)
330{
331 struct map *map = NULL;
332 struct dso *dso = dso__new(name);
333
334 if (dso)
335 map = map__new2(0, dso, MAP__FUNCTION);
336
337 return map;
338}
339
340struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
341 const char *short_name, int dso_type)
342{
343 /*
344 * The kernel dso could be created by build_id processing.
345 */
346 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name);
347
348 /*
349 * We need to run this in all cases, since during the build_id
350 * processing we had no idea this was the kernel dso.
351 */
352 if (dso != NULL) {
353 dso__set_short_name(dso, short_name);
354 dso->kernel = dso_type;
355 }
356
357 return dso;
358}
359
360void dso__set_long_name(struct dso *dso, char *name)
361{
362 if (name == NULL)
363 return;
364 dso->long_name = name;
365 dso->long_name_len = strlen(name);
366}
367
368void dso__set_short_name(struct dso *dso, const char *name)
369{
370 if (name == NULL)
371 return;
372 dso->short_name = name;
373 dso->short_name_len = strlen(name);
374}
375
376static void dso__set_basename(struct dso *dso)
377{
378 dso__set_short_name(dso, basename(dso->long_name));
379}
380
381int dso__name_len(const struct dso *dso)
382{
383 if (!dso)
384 return strlen("[unknown]");
385 if (verbose)
386 return dso->long_name_len;
387
388 return dso->short_name_len;
389}
390
391bool dso__loaded(const struct dso *dso, enum map_type type)
392{
393 return dso->loaded & (1 << type);
394}
395
396bool dso__sorted_by_name(const struct dso *dso, enum map_type type)
397{
398 return dso->sorted_by_name & (1 << type);
399}
400
401void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
402{
403 dso->sorted_by_name |= (1 << type);
404}
405
406struct dso *dso__new(const char *name)
407{
408 struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
409
410 if (dso != NULL) {
411 int i;
412 strcpy(dso->name, name);
413 dso__set_long_name(dso, dso->name);
414 dso__set_short_name(dso, dso->name);
415 for (i = 0; i < MAP__NR_TYPES; ++i)
416 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
417 dso->cache = RB_ROOT;
418 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
419 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND;
420 dso->loaded = 0;
421 dso->sorted_by_name = 0;
422 dso->has_build_id = 0;
423 dso->kernel = DSO_TYPE_USER;
424 dso->needs_swap = DSO_SWAP__UNSET;
425 INIT_LIST_HEAD(&dso->node);
426 }
427
428 return dso;
429}
430
431void dso__delete(struct dso *dso)
432{
433 int i;
434 for (i = 0; i < MAP__NR_TYPES; ++i)
435 symbols__delete(&dso->symbols[i]);
436 if (dso->sname_alloc)
437 free((char *)dso->short_name);
438 if (dso->lname_alloc)
439 free(dso->long_name);
440 dso_cache__free(&dso->cache);
441 free(dso);
442}
443
444void dso__set_build_id(struct dso *dso, void *build_id)
445{
446 memcpy(dso->build_id, build_id, sizeof(dso->build_id));
447 dso->has_build_id = 1;
448}
449
450bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
451{
452 return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
453}
454
455void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
456{
457 char path[PATH_MAX];
458
459 if (machine__is_default_guest(machine))
460 return;
461 sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
462 if (sysfs__read_build_id(path, dso->build_id,
463 sizeof(dso->build_id)) == 0)
464 dso->has_build_id = true;
465}
466
467int dso__kernel_module_get_build_id(struct dso *dso,
468 const char *root_dir)
469{
470 char filename[PATH_MAX];
471 /*
472 * kernel module short names are of the form "[module]" and
473 * we need just "module" here.
474 */
475 const char *name = dso->short_name + 1;
476
477 snprintf(filename, sizeof(filename),
478 "%s/sys/module/%.*s/notes/.note.gnu.build-id",
479 root_dir, (int)strlen(name) - 1, name);
480
481 if (sysfs__read_build_id(filename, dso->build_id,
482 sizeof(dso->build_id)) == 0)
483 dso->has_build_id = true;
484
485 return 0;
486}
487
488bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
489{
490 bool have_build_id = false;
491 struct dso *pos;
492
493 list_for_each_entry(pos, head, node) {
494 if (with_hits && !pos->hit)
495 continue;
496 if (pos->has_build_id) {
497 have_build_id = true;
498 continue;
499 }
500 if (filename__read_build_id(pos->long_name, pos->build_id,
501 sizeof(pos->build_id)) > 0) {
502 have_build_id = true;
503 pos->has_build_id = true;
504 }
505 }
506
507 return have_build_id;
508}
509
510void dsos__add(struct list_head *head, struct dso *dso)
511{
512 list_add_tail(&dso->node, head);
513}
514
515struct dso *dsos__find(struct list_head *head, const char *name)
516{
517 struct dso *pos;
518
519 list_for_each_entry(pos, head, node)
520 if (strcmp(pos->long_name, name) == 0)
521 return pos;
522 return NULL;
523}
524
525struct dso *__dsos__findnew(struct list_head *head, const char *name)
526{
527 struct dso *dso = dsos__find(head, name);
528
529 if (!dso) {
530 dso = dso__new(name);
531 if (dso != NULL) {
532 dsos__add(head, dso);
533 dso__set_basename(dso);
534 }
535 }
536
537 return dso;
538}
539
540size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
541 bool with_hits)
542{
543 struct dso *pos;
544 size_t ret = 0;
545
546 list_for_each_entry(pos, head, node) {
547 if (with_hits && !pos->hit)
548 continue;
549 ret += dso__fprintf_buildid(pos, fp);
550 ret += fprintf(fp, " %s\n", pos->long_name);
551 }
552 return ret;
553}
554
555size_t __dsos__fprintf(struct list_head *head, FILE *fp)
556{
557 struct dso *pos;
558 size_t ret = 0;
559
560 list_for_each_entry(pos, head, node) {
561 int i;
562 for (i = 0; i < MAP__NR_TYPES; ++i)
563 ret += dso__fprintf(pos, i, fp);
564 }
565
566 return ret;
567}
568
569size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
570{
571 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
572
573 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
574 return fprintf(fp, "%s", sbuild_id);
575}
576
577size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
578{
579 struct rb_node *nd;
580 size_t ret = fprintf(fp, "dso: %s (", dso->short_name);
581
582 if (dso->short_name != dso->long_name)
583 ret += fprintf(fp, "%s, ", dso->long_name);
584 ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
585 dso->loaded ? "" : "NOT ");
586 ret += dso__fprintf_buildid(dso, fp);
587 ret += fprintf(fp, ")\n");
588 for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
589 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
590 ret += symbol__fprintf(pos, fp);
591 }
592
593 return ret;
594}
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
new file mode 100644
index 000000000000..e03276940b99
--- /dev/null
+++ b/tools/perf/util/dso.h
@@ -0,0 +1,148 @@
1#ifndef __PERF_DSO
2#define __PERF_DSO
3
4#include <linux/types.h>
5#include <linux/rbtree.h>
6#include "types.h"
7#include "map.h"
8
9enum dso_binary_type {
10 DSO_BINARY_TYPE__KALLSYMS = 0,
11 DSO_BINARY_TYPE__GUEST_KALLSYMS,
12 DSO_BINARY_TYPE__VMLINUX,
13 DSO_BINARY_TYPE__GUEST_VMLINUX,
14 DSO_BINARY_TYPE__JAVA_JIT,
15 DSO_BINARY_TYPE__DEBUGLINK,
16 DSO_BINARY_TYPE__BUILD_ID_CACHE,
17 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
18 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
19 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
20 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
21 DSO_BINARY_TYPE__GUEST_KMODULE,
22 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
23 DSO_BINARY_TYPE__NOT_FOUND,
24};
25
26enum dso_kernel_type {
27 DSO_TYPE_USER = 0,
28 DSO_TYPE_KERNEL,
29 DSO_TYPE_GUEST_KERNEL
30};
31
32enum dso_swap_type {
33 DSO_SWAP__UNSET,
34 DSO_SWAP__NO,
35 DSO_SWAP__YES,
36};
37
38#define DSO__SWAP(dso, type, val) \
39({ \
40 type ____r = val; \
41 BUG_ON(dso->needs_swap == DSO_SWAP__UNSET); \
42 if (dso->needs_swap == DSO_SWAP__YES) { \
43 switch (sizeof(____r)) { \
44 case 2: \
45 ____r = bswap_16(val); \
46 break; \
47 case 4: \
48 ____r = bswap_32(val); \
49 break; \
50 case 8: \
51 ____r = bswap_64(val); \
52 break; \
53 default: \
54 BUG_ON(1); \
55 } \
56 } \
57 ____r; \
58})
59
60#define DSO__DATA_CACHE_SIZE 4096
61#define DSO__DATA_CACHE_MASK ~(DSO__DATA_CACHE_SIZE - 1)
62
63struct dso_cache {
64 struct rb_node rb_node;
65 u64 offset;
66 u64 size;
67 char data[0];
68};
69
70struct dso {
71 struct list_head node;
72 struct rb_root symbols[MAP__NR_TYPES];
73 struct rb_root symbol_names[MAP__NR_TYPES];
74 struct rb_root cache;
75 enum dso_kernel_type kernel;
76 enum dso_swap_type needs_swap;
77 enum dso_binary_type symtab_type;
78 enum dso_binary_type data_type;
79 u8 adjust_symbols:1;
80 u8 has_build_id:1;
81 u8 hit:1;
82 u8 annotate_warned:1;
83 u8 sname_alloc:1;
84 u8 lname_alloc:1;
85 u8 sorted_by_name;
86 u8 loaded;
87 u8 build_id[BUILD_ID_SIZE];
88 const char *short_name;
89 char *long_name;
90 u16 long_name_len;
91 u16 short_name_len;
92 char name[0];
93};
94
95static inline void dso__set_loaded(struct dso *dso, enum map_type type)
96{
97 dso->loaded |= (1 << type);
98}
99
100struct dso *dso__new(const char *name);
101void dso__delete(struct dso *dso);
102
103void dso__set_short_name(struct dso *dso, const char *name);
104void dso__set_long_name(struct dso *dso, char *name);
105
106int dso__name_len(const struct dso *dso);
107
108bool dso__loaded(const struct dso *dso, enum map_type type);
109
110bool dso__sorted_by_name(const struct dso *dso, enum map_type type);
111void dso__set_sorted_by_name(struct dso *dso, enum map_type type);
112void dso__sort_by_name(struct dso *dso, enum map_type type);
113
114void dso__set_build_id(struct dso *dso, void *build_id);
115bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
116void dso__read_running_kernel_build_id(struct dso *dso,
117 struct machine *machine);
118int dso__kernel_module_get_build_id(struct dso *dso, const char *root_dir);
119
120char dso__symtab_origin(const struct dso *dso);
121int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
122 char *root_dir, char *file, size_t size);
123
124int dso__data_fd(struct dso *dso, struct machine *machine);
125ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
126 u64 offset, u8 *data, ssize_t size);
127ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
128 struct machine *machine, u64 addr,
129 u8 *data, ssize_t size);
130
131struct map *dso__new_map(const char *name);
132struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
133 const char *short_name, int dso_type);
134
135void dsos__add(struct list_head *head, struct dso *dso);
136struct dso *dsos__find(struct list_head *head, const char *name);
137struct dso *__dsos__findnew(struct list_head *head, const char *name);
138bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
139
140size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
141 bool with_hits);
142size_t __dsos__fprintf(struct list_head *head, FILE *fp);
143
144size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
145size_t dso__fprintf_symbols_by_name(struct dso *dso,
146 enum map_type type, FILE *fp);
147size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
148#endif /* __PERF_DSO */
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index da97aff5bd75..0d573ff4771a 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -6,6 +6,7 @@
6 6
7#include "../perf.h" 7#include "../perf.h"
8#include "map.h" 8#include "map.h"
9#include "build-id.h"
9 10
10/* 11/*
11 * PERF_SAMPLE_IP | PERF_SAMPLE_TID | * 12 * PERF_SAMPLE_IP | PERF_SAMPLE_TID | *
@@ -96,8 +97,6 @@ struct perf_sample {
96 struct stack_dump user_stack; 97 struct stack_dump user_stack;
97}; 98};
98 99
99#define BUILD_ID_SIZE 20
100
101struct build_id_event { 100struct build_id_event {
102 struct perf_event_header header; 101 struct perf_event_header header;
103 pid_t pid; 102 pid_t pid;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 7daad237dea5..195a47a8f052 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -23,6 +23,7 @@
23#include "pmu.h" 23#include "pmu.h"
24#include "vdso.h" 24#include "vdso.h"
25#include "strbuf.h" 25#include "strbuf.h"
26#include "build-id.h"
26 27
27static bool no_buildid_cache = false; 28static bool no_buildid_cache = false;
28 29
@@ -2340,6 +2341,16 @@ static int try_all_pipe_abis(uint64_t hdr_sz, struct perf_header *ph)
2340 return -1; 2341 return -1;
2341} 2342}
2342 2343
2344bool is_perf_magic(u64 magic)
2345{
2346 if (!memcmp(&magic, __perf_magic1, sizeof(magic))
2347 || magic == __perf_magic2
2348 || magic == __perf_magic2_sw)
2349 return true;
2350
2351 return false;
2352}
2353
2343static int check_magic_endian(u64 magic, uint64_t hdr_sz, 2354static int check_magic_endian(u64 magic, uint64_t hdr_sz,
2344 bool is_pipe, struct perf_header *ph) 2355 bool is_pipe, struct perf_header *ph)
2345{ 2356{
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 879d215cdac9..5f1cd6884f37 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -154,6 +154,7 @@ int perf_event__synthesize_build_id(struct perf_tool *tool,
154int perf_event__process_build_id(struct perf_tool *tool, 154int perf_event__process_build_id(struct perf_tool *tool,
155 union perf_event *event, 155 union perf_event *event,
156 struct perf_session *session); 156 struct perf_session *session);
157bool is_perf_magic(u64 magic);
157 158
158/* 159/*
159 * arch specific callback 160 * arch specific callback
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index c751624d4153..b87460971736 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -165,6 +165,7 @@ int hist_entry__tui_annotate(struct hist_entry *he, int evidx,
165int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 165int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
166 void(*timer)(void *arg), void *arg, 166 void(*timer)(void *arg), void *arg,
167 int refresh); 167 int refresh);
168int script_browse(const char *script_opt);
168#else 169#else
169static inline 170static inline
170int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, 171int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
@@ -186,6 +187,12 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self
186{ 187{
187 return 0; 188 return 0;
188} 189}
190
191static inline int script_browse(const char *script_opt)
192{
193 return 0;
194}
195
189#define K_LEFT -1 196#define K_LEFT -1
190#define K_RIGHT -2 197#define K_RIGHT -2
191#endif 198#endif
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 6109fa4d14cd..9b40c444039c 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -10,6 +10,7 @@
10#include "thread.h" 10#include "thread.h"
11#include "strlist.h" 11#include "strlist.h"
12#include "vdso.h" 12#include "vdso.h"
13#include "build-id.h"
13 14
14const char *map_type__name[MAP__NR_TYPES] = { 15const char *map_type__name[MAP__NR_TYPES] = {
15 [MAP__FUNCTION] = "Functions", 16 [MAP__FUNCTION] = "Functions",
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 3a3efcf3e4e9..c0b785b50849 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -827,8 +827,6 @@ int parse_events(struct perf_evlist *evlist, const char *str,
827 * Both call perf_evlist__delete in case of error, so we dont 827 * Both call perf_evlist__delete in case of error, so we dont
828 * need to bother. 828 * need to bother.
829 */ 829 */
830 fprintf(stderr, "invalid or unsupported event: '%s'\n", str);
831 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
832 return ret; 830 return ret;
833} 831}
834 832
@@ -836,7 +834,13 @@ int parse_events_option(const struct option *opt, const char *str,
836 int unset __maybe_unused) 834 int unset __maybe_unused)
837{ 835{
838 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value; 836 struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
839 return parse_events(evlist, str, unset); 837 int ret = parse_events(evlist, str, unset);
838
839 if (ret) {
840 fprintf(stderr, "invalid or unsupported event: '%s'\n", str);
841 fprintf(stderr, "Run 'perf list' for a list of valid events\n");
842 }
843 return ret;
840} 844}
841 845
842int parse_filter(const struct option *opt, const char *str, 846int parse_filter(const struct option *opt, const char *str,
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 9181bf212fb9..a2657fd96837 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -1015,6 +1015,8 @@ PyMODINIT_FUNC initperf(void)
1015 pyrf_cpu_map__setup_types() < 0) 1015 pyrf_cpu_map__setup_types() < 0)
1016 return; 1016 return;
1017 1017
1018 page_size = sysconf(_SC_PAGE_SIZE);
1019
1018 Py_INCREF(&pyrf_evlist__type); 1020 Py_INCREF(&pyrf_evlist__type);
1019 PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type); 1021 PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
1020 1022
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 32170590892d..346707df04b9 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -314,6 +314,24 @@ int strtailcmp(const char *s1, const char *s2)
314} 314}
315 315
316/** 316/**
317 * strxfrchar - Locate and replace character in @s
318 * @s: The string to be searched/changed.
319 * @from: Source character to be replaced.
320 * @to: Destination character.
321 *
322 * Return pointer to the changed string.
323 */
324char *strxfrchar(char *s, char from, char to)
325{
326 char *p = s;
327
328 while ((p = strchr(p, from)) != NULL)
329 *p++ = to;
330
331 return s;
332}
333
334/**
317 * rtrim - Removes trailing whitespace from @s. 335 * rtrim - Removes trailing whitespace from @s.
318 * @s: The string to be stripped. 336 * @s: The string to be stripped.
319 * 337 *
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e2e8c697cffe..624c65e6ab98 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -23,7 +23,6 @@
23#define KSYM_NAME_LEN 256 23#define KSYM_NAME_LEN 256
24#endif 24#endif
25 25
26static void dso_cache__free(struct rb_root *root);
27static int dso__load_kernel_sym(struct dso *dso, struct map *map, 26static int dso__load_kernel_sym(struct dso *dso, struct map *map,
28 symbol_filter_t filter); 27 symbol_filter_t filter);
29static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 28static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
@@ -56,39 +55,6 @@ static enum dso_binary_type binary_type_symtab[] = {
56 55
57#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab) 56#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab)
58 57
59static enum dso_binary_type binary_type_data[] = {
60 DSO_BINARY_TYPE__BUILD_ID_CACHE,
61 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
62 DSO_BINARY_TYPE__NOT_FOUND,
63};
64
65#define DSO_BINARY_TYPE__DATA_CNT ARRAY_SIZE(binary_type_data)
66
67int dso__name_len(const struct dso *dso)
68{
69 if (!dso)
70 return strlen("[unknown]");
71 if (verbose)
72 return dso->long_name_len;
73
74 return dso->short_name_len;
75}
76
77bool dso__loaded(const struct dso *dso, enum map_type type)
78{
79 return dso->loaded & (1 << type);
80}
81
82bool dso__sorted_by_name(const struct dso *dso, enum map_type type)
83{
84 return dso->sorted_by_name & (1 << type);
85}
86
87static void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
88{
89 dso->sorted_by_name |= (1 << type);
90}
91
92bool symbol_type__is_a(char symbol_type, enum map_type map_type) 58bool symbol_type__is_a(char symbol_type, enum map_type map_type)
93{ 59{
94 symbol_type = toupper(symbol_type); 60 symbol_type = toupper(symbol_type);
@@ -270,7 +236,7 @@ void symbol__delete(struct symbol *sym)
270 free(((void *)sym) - symbol_conf.priv_size); 236 free(((void *)sym) - symbol_conf.priv_size);
271} 237}
272 238
273static size_t symbol__fprintf(struct symbol *sym, FILE *fp) 239size_t symbol__fprintf(struct symbol *sym, FILE *fp)
274{ 240{
275 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n", 241 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n",
276 sym->start, sym->end, 242 sym->start, sym->end,
@@ -301,53 +267,7 @@ size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp)
301 return symbol__fprintf_symname_offs(sym, NULL, fp); 267 return symbol__fprintf_symname_offs(sym, NULL, fp);
302} 268}
303 269
304void dso__set_long_name(struct dso *dso, char *name) 270void symbols__delete(struct rb_root *symbols)
305{
306 if (name == NULL)
307 return;
308 dso->long_name = name;
309 dso->long_name_len = strlen(name);
310}
311
312static void dso__set_short_name(struct dso *dso, const char *name)
313{
314 if (name == NULL)
315 return;
316 dso->short_name = name;
317 dso->short_name_len = strlen(name);
318}
319
320static void dso__set_basename(struct dso *dso)
321{
322 dso__set_short_name(dso, basename(dso->long_name));
323}
324
325struct dso *dso__new(const char *name)
326{
327 struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
328
329 if (dso != NULL) {
330 int i;
331 strcpy(dso->name, name);
332 dso__set_long_name(dso, dso->name);
333 dso__set_short_name(dso, dso->name);
334 for (i = 0; i < MAP__NR_TYPES; ++i)
335 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
336 dso->cache = RB_ROOT;
337 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
338 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND;
339 dso->loaded = 0;
340 dso->sorted_by_name = 0;
341 dso->has_build_id = 0;
342 dso->kernel = DSO_TYPE_USER;
343 dso->needs_swap = DSO_SWAP__UNSET;
344 INIT_LIST_HEAD(&dso->node);
345 }
346
347 return dso;
348}
349
350static void symbols__delete(struct rb_root *symbols)
351{ 271{
352 struct symbol *pos; 272 struct symbol *pos;
353 struct rb_node *next = rb_first(symbols); 273 struct rb_node *next = rb_first(symbols);
@@ -360,25 +280,6 @@ static void symbols__delete(struct rb_root *symbols)
360 } 280 }
361} 281}
362 282
363void dso__delete(struct dso *dso)
364{
365 int i;
366 for (i = 0; i < MAP__NR_TYPES; ++i)
367 symbols__delete(&dso->symbols[i]);
368 if (dso->sname_alloc)
369 free((char *)dso->short_name);
370 if (dso->lname_alloc)
371 free(dso->long_name);
372 dso_cache__free(&dso->cache);
373 free(dso);
374}
375
376void dso__set_build_id(struct dso *dso, void *build_id)
377{
378 memcpy(dso->build_id, build_id, sizeof(dso->build_id));
379 dso->has_build_id = 1;
380}
381
382void symbols__insert(struct rb_root *symbols, struct symbol *sym) 283void symbols__insert(struct rb_root *symbols, struct symbol *sym)
383{ 284{
384 struct rb_node **p = &symbols->rb_node; 285 struct rb_node **p = &symbols->rb_node;
@@ -504,29 +405,6 @@ void dso__sort_by_name(struct dso *dso, enum map_type type)
504 &dso->symbols[type]); 405 &dso->symbols[type]);
505} 406}
506 407
507int build_id__sprintf(const u8 *build_id, int len, char *bf)
508{
509 char *bid = bf;
510 const u8 *raw = build_id;
511 int i;
512
513 for (i = 0; i < len; ++i) {
514 sprintf(bid, "%02x", *raw);
515 ++raw;
516 bid += 2;
517 }
518
519 return raw - build_id;
520}
521
522size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
523{
524 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
525
526 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
527 return fprintf(fp, "%s", sbuild_id);
528}
529
530size_t dso__fprintf_symbols_by_name(struct dso *dso, 408size_t dso__fprintf_symbols_by_name(struct dso *dso,
531 enum map_type type, FILE *fp) 409 enum map_type type, FILE *fp)
532{ 410{
@@ -542,25 +420,6 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso,
542 return ret; 420 return ret;
543} 421}
544 422
545size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
546{
547 struct rb_node *nd;
548 size_t ret = fprintf(fp, "dso: %s (", dso->short_name);
549
550 if (dso->short_name != dso->long_name)
551 ret += fprintf(fp, "%s, ", dso->long_name);
552 ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
553 dso->loaded ? "" : "NOT ");
554 ret += dso__fprintf_buildid(dso, fp);
555 ret += fprintf(fp, ")\n");
556 for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
557 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
558 ret += symbol__fprintf(pos, fp);
559 }
560
561 return ret;
562}
563
564int kallsyms__parse(const char *filename, void *arg, 423int kallsyms__parse(const char *filename, void *arg,
565 int (*process_symbol)(void *arg, const char *name, 424 int (*process_symbol)(void *arg, const char *name,
566 char type, u64 start)) 425 char type, u64 start))
@@ -892,136 +751,6 @@ out_failure:
892 return -1; 751 return -1;
893} 752}
894 753
895bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
896{
897 return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
898}
899
900bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
901{
902 bool have_build_id = false;
903 struct dso *pos;
904
905 list_for_each_entry(pos, head, node) {
906 if (with_hits && !pos->hit)
907 continue;
908 if (pos->has_build_id) {
909 have_build_id = true;
910 continue;
911 }
912 if (filename__read_build_id(pos->long_name, pos->build_id,
913 sizeof(pos->build_id)) > 0) {
914 have_build_id = true;
915 pos->has_build_id = true;
916 }
917 }
918
919 return have_build_id;
920}
921
922char dso__symtab_origin(const struct dso *dso)
923{
924 static const char origin[] = {
925 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
926 [DSO_BINARY_TYPE__VMLINUX] = 'v',
927 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
928 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
929 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
930 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
931 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
932 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
933 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
934 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
935 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
936 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
937 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
938 };
939
940 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
941 return '!';
942 return origin[dso->symtab_type];
943}
944
945int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
946 char *root_dir, char *file, size_t size)
947{
948 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
949 int ret = 0;
950
951 switch (type) {
952 case DSO_BINARY_TYPE__DEBUGLINK: {
953 char *debuglink;
954
955 strncpy(file, dso->long_name, size);
956 debuglink = file + dso->long_name_len;
957 while (debuglink != file && *debuglink != '/')
958 debuglink--;
959 if (*debuglink == '/')
960 debuglink++;
961 filename__read_debuglink(dso->long_name, debuglink,
962 size - (debuglink - file));
963 }
964 break;
965 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
966 /* skip the locally configured cache if a symfs is given */
967 if (symbol_conf.symfs[0] ||
968 (dso__build_id_filename(dso, file, size) == NULL))
969 ret = -1;
970 break;
971
972 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
973 snprintf(file, size, "%s/usr/lib/debug%s.debug",
974 symbol_conf.symfs, dso->long_name);
975 break;
976
977 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
978 snprintf(file, size, "%s/usr/lib/debug%s",
979 symbol_conf.symfs, dso->long_name);
980 break;
981
982 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
983 if (!dso->has_build_id) {
984 ret = -1;
985 break;
986 }
987
988 build_id__sprintf(dso->build_id,
989 sizeof(dso->build_id),
990 build_id_hex);
991 snprintf(file, size,
992 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
993 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
994 break;
995
996 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
997 snprintf(file, size, "%s%s",
998 symbol_conf.symfs, dso->long_name);
999 break;
1000
1001 case DSO_BINARY_TYPE__GUEST_KMODULE:
1002 snprintf(file, size, "%s%s%s", symbol_conf.symfs,
1003 root_dir, dso->long_name);
1004 break;
1005
1006 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
1007 snprintf(file, size, "%s%s", symbol_conf.symfs,
1008 dso->long_name);
1009 break;
1010
1011 default:
1012 case DSO_BINARY_TYPE__KALLSYMS:
1013 case DSO_BINARY_TYPE__VMLINUX:
1014 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
1015 case DSO_BINARY_TYPE__GUEST_VMLINUX:
1016 case DSO_BINARY_TYPE__JAVA_JIT:
1017 case DSO_BINARY_TYPE__NOT_FOUND:
1018 ret = -1;
1019 break;
1020 }
1021
1022 return ret;
1023}
1024
1025int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) 754int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1026{ 755{
1027 char *name; 756 char *name;
@@ -1157,27 +886,6 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
1157 return NULL; 886 return NULL;
1158} 887}
1159 888
1160static int dso__kernel_module_get_build_id(struct dso *dso,
1161 const char *root_dir)
1162{
1163 char filename[PATH_MAX];
1164 /*
1165 * kernel module short names are of the form "[module]" and
1166 * we need just "module" here.
1167 */
1168 const char *name = dso->short_name + 1;
1169
1170 snprintf(filename, sizeof(filename),
1171 "%s/sys/module/%.*s/notes/.note.gnu.build-id",
1172 root_dir, (int)strlen(name) - 1, name);
1173
1174 if (sysfs__read_build_id(filename, dso->build_id,
1175 sizeof(dso->build_id)) == 0)
1176 dso->has_build_id = true;
1177
1178 return 0;
1179}
1180
1181static int map_groups__set_modules_path_dir(struct map_groups *mg, 889static int map_groups__set_modules_path_dir(struct map_groups *mg,
1182 const char *dir_name) 890 const char *dir_name)
1183{ 891{
@@ -1591,50 +1299,6 @@ out_try_fixup:
1591 return err; 1299 return err;
1592} 1300}
1593 1301
1594void dsos__add(struct list_head *head, struct dso *dso)
1595{
1596 list_add_tail(&dso->node, head);
1597}
1598
1599struct dso *dsos__find(struct list_head *head, const char *name)
1600{
1601 struct dso *pos;
1602
1603 list_for_each_entry(pos, head, node)
1604 if (strcmp(pos->long_name, name) == 0)
1605 return pos;
1606 return NULL;
1607}
1608
1609struct dso *__dsos__findnew(struct list_head *head, const char *name)
1610{
1611 struct dso *dso = dsos__find(head, name);
1612
1613 if (!dso) {
1614 dso = dso__new(name);
1615 if (dso != NULL) {
1616 dsos__add(head, dso);
1617 dso__set_basename(dso);
1618 }
1619 }
1620
1621 return dso;
1622}
1623
1624size_t __dsos__fprintf(struct list_head *head, FILE *fp)
1625{
1626 struct dso *pos;
1627 size_t ret = 0;
1628
1629 list_for_each_entry(pos, head, node) {
1630 int i;
1631 for (i = 0; i < MAP__NR_TYPES; ++i)
1632 ret += dso__fprintf(pos, i, fp);
1633 }
1634
1635 return ret;
1636}
1637
1638size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp) 1302size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
1639{ 1303{
1640 struct rb_node *nd; 1304 struct rb_node *nd;
@@ -1649,21 +1313,6 @@ size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
1649 return ret; 1313 return ret;
1650} 1314}
1651 1315
1652static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
1653 bool with_hits)
1654{
1655 struct dso *pos;
1656 size_t ret = 0;
1657
1658 list_for_each_entry(pos, head, node) {
1659 if (with_hits && !pos->hit)
1660 continue;
1661 ret += dso__fprintf_buildid(pos, fp);
1662 ret += fprintf(fp, " %s\n", pos->long_name);
1663 }
1664 return ret;
1665}
1666
1667size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 1316size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
1668 bool with_hits) 1317 bool with_hits)
1669{ 1318{
@@ -1684,39 +1333,6 @@ size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
1684 return ret; 1333 return ret;
1685} 1334}
1686 1335
1687static struct dso*
1688dso__kernel_findnew(struct machine *machine, const char *name,
1689 const char *short_name, int dso_type)
1690{
1691 /*
1692 * The kernel dso could be created by build_id processing.
1693 */
1694 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name);
1695
1696 /*
1697 * We need to run this in all cases, since during the build_id
1698 * processing we had no idea this was the kernel dso.
1699 */
1700 if (dso != NULL) {
1701 dso__set_short_name(dso, short_name);
1702 dso->kernel = dso_type;
1703 }
1704
1705 return dso;
1706}
1707
1708void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
1709{
1710 char path[PATH_MAX];
1711
1712 if (machine__is_default_guest(machine))
1713 return;
1714 sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
1715 if (sysfs__read_build_id(path, dso->build_id,
1716 sizeof(dso->build_id)) == 0)
1717 dso->has_build_id = true;
1718}
1719
1720static struct dso *machine__get_kernel(struct machine *machine) 1336static struct dso *machine__get_kernel(struct machine *machine)
1721{ 1337{
1722 const char *vmlinux_name = NULL; 1338 const char *vmlinux_name = NULL;
@@ -2065,49 +1681,6 @@ int machines__create_kernel_maps(struct rb_root *machines, pid_t pid)
2065 return machine__create_kernel_maps(machine); 1681 return machine__create_kernel_maps(machine);
2066} 1682}
2067 1683
2068static int hex(char ch)
2069{
2070 if ((ch >= '0') && (ch <= '9'))
2071 return ch - '0';
2072 if ((ch >= 'a') && (ch <= 'f'))
2073 return ch - 'a' + 10;
2074 if ((ch >= 'A') && (ch <= 'F'))
2075 return ch - 'A' + 10;
2076 return -1;
2077}
2078
2079/*
2080 * While we find nice hex chars, build a long_val.
2081 * Return number of chars processed.
2082 */
2083int hex2u64(const char *ptr, u64 *long_val)
2084{
2085 const char *p = ptr;
2086 *long_val = 0;
2087
2088 while (*p) {
2089 const int hex_val = hex(*p);
2090
2091 if (hex_val < 0)
2092 break;
2093
2094 *long_val = (*long_val << 4) | hex_val;
2095 p++;
2096 }
2097
2098 return p - ptr;
2099}
2100
2101char *strxfrchar(char *s, char from, char to)
2102{
2103 char *p = s;
2104
2105 while ((p = strchr(p, from)) != NULL)
2106 *p++ = to;
2107
2108 return s;
2109}
2110
2111int machines__create_guest_kernel_maps(struct rb_root *machines) 1684int machines__create_guest_kernel_maps(struct rb_root *machines)
2112{ 1685{
2113 int ret = 0; 1686 int ret = 0;
@@ -2202,229 +1775,3 @@ int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
2202 1775
2203 return ret; 1776 return ret;
2204} 1777}
2205
2206struct map *dso__new_map(const char *name)
2207{
2208 struct map *map = NULL;
2209 struct dso *dso = dso__new(name);
2210
2211 if (dso)
2212 map = map__new2(0, dso, MAP__FUNCTION);
2213
2214 return map;
2215}
2216
2217static int open_dso(struct dso *dso, struct machine *machine)
2218{
2219 char *root_dir = (char *) "";
2220 char *name;
2221 int fd;
2222
2223 name = malloc(PATH_MAX);
2224 if (!name)
2225 return -ENOMEM;
2226
2227 if (machine)
2228 root_dir = machine->root_dir;
2229
2230 if (dso__binary_type_file(dso, dso->data_type,
2231 root_dir, name, PATH_MAX)) {
2232 free(name);
2233 return -EINVAL;
2234 }
2235
2236 fd = open(name, O_RDONLY);
2237 free(name);
2238 return fd;
2239}
2240
2241int dso__data_fd(struct dso *dso, struct machine *machine)
2242{
2243 int i = 0;
2244
2245 if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND)
2246 return open_dso(dso, machine);
2247
2248 do {
2249 int fd;
2250
2251 dso->data_type = binary_type_data[i++];
2252
2253 fd = open_dso(dso, machine);
2254 if (fd >= 0)
2255 return fd;
2256
2257 } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND);
2258
2259 return -EINVAL;
2260}
2261
2262static void
2263dso_cache__free(struct rb_root *root)
2264{
2265 struct rb_node *next = rb_first(root);
2266
2267 while (next) {
2268 struct dso_cache *cache;
2269
2270 cache = rb_entry(next, struct dso_cache, rb_node);
2271 next = rb_next(&cache->rb_node);
2272 rb_erase(&cache->rb_node, root);
2273 free(cache);
2274 }
2275}
2276
2277static struct dso_cache*
2278dso_cache__find(struct rb_root *root, u64 offset)
2279{
2280 struct rb_node **p = &root->rb_node;
2281 struct rb_node *parent = NULL;
2282 struct dso_cache *cache;
2283
2284 while (*p != NULL) {
2285 u64 end;
2286
2287 parent = *p;
2288 cache = rb_entry(parent, struct dso_cache, rb_node);
2289 end = cache->offset + DSO__DATA_CACHE_SIZE;
2290
2291 if (offset < cache->offset)
2292 p = &(*p)->rb_left;
2293 else if (offset >= end)
2294 p = &(*p)->rb_right;
2295 else
2296 return cache;
2297 }
2298 return NULL;
2299}
2300
2301static void
2302dso_cache__insert(struct rb_root *root, struct dso_cache *new)
2303{
2304 struct rb_node **p = &root->rb_node;
2305 struct rb_node *parent = NULL;
2306 struct dso_cache *cache;
2307 u64 offset = new->offset;
2308
2309 while (*p != NULL) {
2310 u64 end;
2311
2312 parent = *p;
2313 cache = rb_entry(parent, struct dso_cache, rb_node);
2314 end = cache->offset + DSO__DATA_CACHE_SIZE;
2315
2316 if (offset < cache->offset)
2317 p = &(*p)->rb_left;
2318 else if (offset >= end)
2319 p = &(*p)->rb_right;
2320 }
2321
2322 rb_link_node(&new->rb_node, parent, p);
2323 rb_insert_color(&new->rb_node, root);
2324}
2325
2326static ssize_t
2327dso_cache__memcpy(struct dso_cache *cache, u64 offset,
2328 u8 *data, u64 size)
2329{
2330 u64 cache_offset = offset - cache->offset;
2331 u64 cache_size = min(cache->size - cache_offset, size);
2332
2333 memcpy(data, cache->data + cache_offset, cache_size);
2334 return cache_size;
2335}
2336
2337static ssize_t
2338dso_cache__read(struct dso *dso, struct machine *machine,
2339 u64 offset, u8 *data, ssize_t size)
2340{
2341 struct dso_cache *cache;
2342 ssize_t ret;
2343 int fd;
2344
2345 fd = dso__data_fd(dso, machine);
2346 if (fd < 0)
2347 return -1;
2348
2349 do {
2350 u64 cache_offset;
2351
2352 ret = -ENOMEM;
2353
2354 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
2355 if (!cache)
2356 break;
2357
2358 cache_offset = offset & DSO__DATA_CACHE_MASK;
2359 ret = -EINVAL;
2360
2361 if (-1 == lseek(fd, cache_offset, SEEK_SET))
2362 break;
2363
2364 ret = read(fd, cache->data, DSO__DATA_CACHE_SIZE);
2365 if (ret <= 0)
2366 break;
2367
2368 cache->offset = cache_offset;
2369 cache->size = ret;
2370 dso_cache__insert(&dso->cache, cache);
2371
2372 ret = dso_cache__memcpy(cache, offset, data, size);
2373
2374 } while (0);
2375
2376 if (ret <= 0)
2377 free(cache);
2378
2379 close(fd);
2380 return ret;
2381}
2382
2383static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
2384 u64 offset, u8 *data, ssize_t size)
2385{
2386 struct dso_cache *cache;
2387
2388 cache = dso_cache__find(&dso->cache, offset);
2389 if (cache)
2390 return dso_cache__memcpy(cache, offset, data, size);
2391 else
2392 return dso_cache__read(dso, machine, offset, data, size);
2393}
2394
2395ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
2396 u64 offset, u8 *data, ssize_t size)
2397{
2398 ssize_t r = 0;
2399 u8 *p = data;
2400
2401 do {
2402 ssize_t ret;
2403
2404 ret = dso_cache_read(dso, machine, offset, p, size);
2405 if (ret < 0)
2406 return ret;
2407
2408 /* Reached EOF, return what we have. */
2409 if (!ret)
2410 break;
2411
2412 BUG_ON(ret > size);
2413
2414 r += ret;
2415 p += ret;
2416 offset += ret;
2417 size -= ret;
2418
2419 } while (size);
2420
2421 return r;
2422}
2423
2424ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
2425 struct machine *machine, u64 addr,
2426 u8 *data, ssize_t size)
2427{
2428 u64 offset = map->map_ip(map, addr);
2429 return dso__data_read_offset(dso, machine, offset, data, size);
2430}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 8b6ef7fac745..863b05bea5ff 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -11,6 +11,7 @@
11#include <stdio.h> 11#include <stdio.h>
12#include <byteswap.h> 12#include <byteswap.h>
13#include <libgen.h> 13#include <libgen.h>
14#include "build-id.h"
14 15
15#ifdef LIBELF_SUPPORT 16#ifdef LIBELF_SUPPORT
16#include <libelf.h> 17#include <libelf.h>
@@ -18,6 +19,8 @@
18#include <elf.h> 19#include <elf.h>
19#endif 20#endif
20 21
22#include "dso.h"
23
21#ifdef HAVE_CPLUS_DEMANGLE 24#ifdef HAVE_CPLUS_DEMANGLE
22extern char *cplus_demangle(const char *, int); 25extern char *cplus_demangle(const char *, int);
23 26
@@ -39,9 +42,6 @@ static inline char *bfd_demangle(void __maybe_unused *v,
39#endif 42#endif
40#endif 43#endif
41 44
42int hex2u64(const char *ptr, u64 *val);
43char *strxfrchar(char *s, char from, char to);
44
45/* 45/*
46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP; 46 * libelf 0.8.x and earlier do not support ELF_C_READ_MMAP;
47 * for newer versions we can use mmap to reduce memory usage: 47 * for newer versions we can use mmap to reduce memory usage:
@@ -57,8 +57,6 @@ char *strxfrchar(char *s, char from, char to);
57#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ 57#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
58#endif 58#endif
59 59
60#define BUILD_ID_SIZE 20
61
62/** struct symbol - symtab entry 60/** struct symbol - symtab entry
63 * 61 *
64 * @ignore - resolvable but tools ignore it (e.g. idle routines) 62 * @ignore - resolvable but tools ignore it (e.g. idle routines)
@@ -74,6 +72,7 @@ struct symbol {
74}; 72};
75 73
76void symbol__delete(struct symbol *sym); 74void symbol__delete(struct symbol *sym);
75void symbols__delete(struct rb_root *symbols);
77 76
78static inline size_t symbol__size(const struct symbol *sym) 77static inline size_t symbol__size(const struct symbol *sym)
79{ 78{
@@ -164,70 +163,6 @@ struct addr_location {
164 s32 cpu; 163 s32 cpu;
165}; 164};
166 165
167enum dso_binary_type {
168 DSO_BINARY_TYPE__KALLSYMS = 0,
169 DSO_BINARY_TYPE__GUEST_KALLSYMS,
170 DSO_BINARY_TYPE__VMLINUX,
171 DSO_BINARY_TYPE__GUEST_VMLINUX,
172 DSO_BINARY_TYPE__JAVA_JIT,
173 DSO_BINARY_TYPE__DEBUGLINK,
174 DSO_BINARY_TYPE__BUILD_ID_CACHE,
175 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
176 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
177 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
178 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
179 DSO_BINARY_TYPE__GUEST_KMODULE,
180 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
181 DSO_BINARY_TYPE__NOT_FOUND,
182};
183
184enum dso_kernel_type {
185 DSO_TYPE_USER = 0,
186 DSO_TYPE_KERNEL,
187 DSO_TYPE_GUEST_KERNEL
188};
189
190enum dso_swap_type {
191 DSO_SWAP__UNSET,
192 DSO_SWAP__NO,
193 DSO_SWAP__YES,
194};
195
196#define DSO__DATA_CACHE_SIZE 4096
197#define DSO__DATA_CACHE_MASK ~(DSO__DATA_CACHE_SIZE - 1)
198
199struct dso_cache {
200 struct rb_node rb_node;
201 u64 offset;
202 u64 size;
203 char data[0];
204};
205
206struct dso {
207 struct list_head node;
208 struct rb_root symbols[MAP__NR_TYPES];
209 struct rb_root symbol_names[MAP__NR_TYPES];
210 struct rb_root cache;
211 enum dso_kernel_type kernel;
212 enum dso_swap_type needs_swap;
213 enum dso_binary_type symtab_type;
214 enum dso_binary_type data_type;
215 u8 adjust_symbols:1;
216 u8 has_build_id:1;
217 u8 hit:1;
218 u8 annotate_warned:1;
219 u8 sname_alloc:1;
220 u8 lname_alloc:1;
221 u8 sorted_by_name;
222 u8 loaded;
223 u8 build_id[BUILD_ID_SIZE];
224 const char *short_name;
225 char *long_name;
226 u16 long_name_len;
227 u16 short_name_len;
228 char name[0];
229};
230
231struct symsrc { 166struct symsrc {
232 char *name; 167 char *name;
233 int fd; 168 int fd;
@@ -258,47 +193,6 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
258bool symsrc__has_symtab(struct symsrc *ss); 193bool symsrc__has_symtab(struct symsrc *ss);
259bool symsrc__possibly_runtime(struct symsrc *ss); 194bool symsrc__possibly_runtime(struct symsrc *ss);
260 195
261#define DSO__SWAP(dso, type, val) \
262({ \
263 type ____r = val; \
264 BUG_ON(dso->needs_swap == DSO_SWAP__UNSET); \
265 if (dso->needs_swap == DSO_SWAP__YES) { \
266 switch (sizeof(____r)) { \
267 case 2: \
268 ____r = bswap_16(val); \
269 break; \
270 case 4: \
271 ____r = bswap_32(val); \
272 break; \
273 case 8: \
274 ____r = bswap_64(val); \
275 break; \
276 default: \
277 BUG_ON(1); \
278 } \
279 } \
280 ____r; \
281})
282
283struct dso *dso__new(const char *name);
284void dso__delete(struct dso *dso);
285
286int dso__name_len(const struct dso *dso);
287
288bool dso__loaded(const struct dso *dso, enum map_type type);
289bool dso__sorted_by_name(const struct dso *dso, enum map_type type);
290
291static inline void dso__set_loaded(struct dso *dso, enum map_type type)
292{
293 dso->loaded |= (1 << type);
294}
295
296void dso__sort_by_name(struct dso *dso, enum map_type type);
297
298void dsos__add(struct list_head *head, struct dso *dso);
299struct dso *dsos__find(struct list_head *head, const char *name);
300struct dso *__dsos__findnew(struct list_head *head, const char *name);
301
302int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); 196int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter);
303int dso__load_vmlinux(struct dso *dso, struct map *map, 197int dso__load_vmlinux(struct dso *dso, struct map *map,
304 const char *vmlinux, symbol_filter_t filter); 198 const char *vmlinux, symbol_filter_t filter);
@@ -311,25 +205,12 @@ int machine__load_kallsyms(struct machine *machine, const char *filename,
311int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 205int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
312 symbol_filter_t filter); 206 symbol_filter_t filter);
313 207
314size_t __dsos__fprintf(struct list_head *head, FILE *fp);
315
316size_t machine__fprintf_dsos_buildid(struct machine *machine, 208size_t machine__fprintf_dsos_buildid(struct machine *machine,
317 FILE *fp, bool with_hits); 209 FILE *fp, bool with_hits);
318size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp); 210size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp);
319size_t machines__fprintf_dsos_buildid(struct rb_root *machines, 211size_t machines__fprintf_dsos_buildid(struct rb_root *machines,
320 FILE *fp, bool with_hits); 212 FILE *fp, bool with_hits);
321size_t dso__fprintf_buildid(struct dso *dso, FILE *fp); 213
322size_t dso__fprintf_symbols_by_name(struct dso *dso,
323 enum map_type type, FILE *fp);
324size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
325
326char dso__symtab_origin(const struct dso *dso);
327void dso__set_long_name(struct dso *dso, char *name);
328void dso__set_build_id(struct dso *dso, void *build_id);
329bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
330void dso__read_running_kernel_build_id(struct dso *dso,
331 struct machine *machine);
332struct map *dso__new_map(const char *name);
333struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, 214struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
334 u64 addr); 215 u64 addr);
335struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 216struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
@@ -337,8 +218,6 @@ struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
337 218
338int filename__read_build_id(const char *filename, void *bf, size_t size); 219int filename__read_build_id(const char *filename, void *bf, size_t size);
339int sysfs__read_build_id(const char *filename, void *bf, size_t size); 220int sysfs__read_build_id(const char *filename, void *bf, size_t size);
340bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
341int build_id__sprintf(const u8 *build_id, int len, char *bf);
342int kallsyms__parse(const char *filename, void *arg, 221int kallsyms__parse(const char *filename, void *arg,
343 int (*process_symbol)(void *arg, const char *name, 222 int (*process_symbol)(void *arg, const char *name,
344 char type, u64 start)); 223 char type, u64 start));
@@ -360,19 +239,11 @@ struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
360size_t symbol__fprintf_symname_offs(const struct symbol *sym, 239size_t symbol__fprintf_symname_offs(const struct symbol *sym,
361 const struct addr_location *al, FILE *fp); 240 const struct addr_location *al, FILE *fp);
362size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); 241size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
242size_t symbol__fprintf(struct symbol *sym, FILE *fp);
363bool symbol_type__is_a(char symbol_type, enum map_type map_type); 243bool symbol_type__is_a(char symbol_type, enum map_type map_type);
364 244
365size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); 245size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
366 246
367int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
368 char *root_dir, char *file, size_t size);
369
370int dso__data_fd(struct dso *dso, struct machine *machine);
371ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
372 u64 offset, u8 *data, ssize_t size);
373ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
374 struct machine *machine, u64 addr,
375 u8 *data, ssize_t size);
376int dso__test_data(void); 247int dso__test_data(void);
377int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 248int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
378 struct symsrc *runtime_ss, symbol_filter_t filter, 249 struct symsrc *runtime_ss, symbol_filter_t filter,
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 637b5cc54362..5906e8426cc7 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -166,6 +166,39 @@ size_t hex_width(u64 v)
166 return n; 166 return n;
167} 167}
168 168
169static int hex(char ch)
170{
171 if ((ch >= '0') && (ch <= '9'))
172 return ch - '0';
173 if ((ch >= 'a') && (ch <= 'f'))
174 return ch - 'a' + 10;
175 if ((ch >= 'A') && (ch <= 'F'))
176 return ch - 'A' + 10;
177 return -1;
178}
179
180/*
181 * While we find nice hex chars, build a long_val.
182 * Return number of chars processed.
183 */
184int hex2u64(const char *ptr, u64 *long_val)
185{
186 const char *p = ptr;
187 *long_val = 0;
188
189 while (*p) {
190 const int hex_val = hex(*p);
191
192 if (hex_val < 0)
193 break;
194
195 *long_val = (*long_val << 4) | hex_val;
196 p++;
197 }
198
199 return p - ptr;
200}
201
169/* Obtain a backtrace and print it to stdout. */ 202/* Obtain a backtrace and print it to stdout. */
170#ifdef BACKTRACE_SUPPORT 203#ifdef BACKTRACE_SUPPORT
171void dump_stack(void) 204void dump_stack(void)
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 0d85209db8f1..c2330918110c 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -240,6 +240,7 @@ void argv_free(char **argv);
240bool strglobmatch(const char *str, const char *pat); 240bool strglobmatch(const char *str, const char *pat);
241bool strlazymatch(const char *str, const char *pat); 241bool strlazymatch(const char *str, const char *pat);
242int strtailcmp(const char *s1, const char *s2); 242int strtailcmp(const char *s1, const char *s2);
243char *strxfrchar(char *s, char from, char to);
243unsigned long convert_unit(unsigned long value, char *unit); 244unsigned long convert_unit(unsigned long value, char *unit);
244int readn(int fd, void *buf, size_t size); 245int readn(int fd, void *buf, size_t size);
245 246
@@ -262,6 +263,7 @@ bool is_power_of_2(unsigned long n)
262} 263}
263 264
264size_t hex_width(u64 v); 265size_t hex_width(u64 v);
266int hex2u64(const char *ptr, u64 *val);
265 267
266char *rtrim(char *s); 268char *rtrim(char *s);
267 269