aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2010-12-22 05:54:50 -0500
committerIngo Molnar <mingo@elte.hu>2010-12-22 05:54:50 -0500
commit8c1df4002aa425973d7d25ffa56c042acd953bed (patch)
tree441e39bf3a43bb3e4c4965ed2081b9bb90edd1ea
parent6c529a266bdc590a870ee2d2092ff6527eff427b (diff)
parent21dd9ae5a4e9f717f3957ec934dd3158129436b8 (diff)
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
-rw-r--r--tools/perf/Documentation/perf-diff.txt2
-rw-r--r--tools/perf/Documentation/perf-probe.txt2
-rw-r--r--tools/perf/Documentation/perf-report.txt3
-rw-r--r--tools/perf/Documentation/perf-timechart.txt2
-rw-r--r--tools/perf/builtin-annotate.c4
-rw-r--r--tools/perf/builtin-buildid-list.c3
-rw-r--r--tools/perf/builtin-diff.c8
-rw-r--r--tools/perf/builtin-inject.c2
-rw-r--r--tools/perf/builtin-kmem.c3
-rw-r--r--tools/perf/builtin-lock.c2
-rw-r--r--tools/perf/builtin-record.c7
-rw-r--r--tools/perf/builtin-report.c6
-rw-r--r--tools/perf/builtin-sched.c3
-rw-r--r--tools/perf/builtin-script.c2
-rw-r--r--tools/perf/builtin-timechart.c5
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/util/hist.c14
-rw-r--r--tools/perf/util/probe-event.c220
-rw-r--r--tools/perf/util/probe-finder.c42
-rw-r--r--tools/perf/util/session.c11
-rw-r--r--tools/perf/util/session.h5
-rw-r--r--tools/perf/util/symbol.c72
-rw-r--r--tools/perf/util/symbol.h1
23 files changed, 277 insertions, 144 deletions
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 6a9ec2b35310..74d7481ed7a6 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -66,6 +66,8 @@ OPTIONS
66--force:: 66--force::
67 Don't complain, do it. 67 Don't complain, do it.
68 68
69--symfs=<directory>::
70 Look for files with symbols relative to this directory.
69 71
70SEE ALSO 72SEE ALSO
71-------- 73--------
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 4e2323276984..86b797a35aa6 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -117,7 +117,7 @@ LINE SYNTAX
117----------- 117-----------
118Line range is described by following syntax. 118Line range is described by following syntax.
119 119
120 "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]" 120 "FUNC[:RLN[+NUM|-RLN2]]|SRC[:ALN[+NUM|-ALN2]]"
121 121
122FUNC specifies the function name of showing lines. 'RLN' is the start line 122FUNC specifies the function name of showing lines. 'RLN' is the start line
123number from function entry line, and 'RLN2' is the end line number. As same as 123number from function entry line, and 'RLN2' is the end line number. As same as
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index fefea77ec6e9..8ba03d6e5398 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -116,6 +116,9 @@ OPTIONS
116--force:: 116--force::
117 Don't complain, do it. 117 Don't complain, do it.
118 118
119--symfs=<directory>::
120 Look for files with symbols relative to this directory.
121
119SEE ALSO 122SEE ALSO
120-------- 123--------
121linkperf:perf-stat[1] 124linkperf:perf-stat[1]
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index 4b1788355eca..d7b79e2ba2ad 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -38,6 +38,8 @@ OPTIONS
38--process:: 38--process::
39 Select the processes to display, by name or PID 39 Select the processes to display, by name or PID
40 40
41--symfs=<directory>::
42 Look for files with symbols relative to this directory.
41 43
42SEE ALSO 44SEE ALSO
43-------- 45--------
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 569a2761b90a..c056cdc06912 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -375,6 +375,8 @@ static struct perf_event_ops event_ops = {
375 .mmap = event__process_mmap, 375 .mmap = event__process_mmap,
376 .comm = event__process_comm, 376 .comm = event__process_comm,
377 .fork = event__process_task, 377 .fork = event__process_task,
378 .ordered_samples = true,
379 .ordering_requires_timestamps = true,
378}; 380};
379 381
380static int __cmd_annotate(void) 382static int __cmd_annotate(void)
@@ -382,7 +384,7 @@ static int __cmd_annotate(void)
382 int ret; 384 int ret;
383 struct perf_session *session; 385 struct perf_session *session;
384 386
385 session = perf_session__new(input_name, O_RDONLY, force, false); 387 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
386 if (session == NULL) 388 if (session == NULL)
387 return -ENOMEM; 389 return -ENOMEM;
388 390
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 44a47e13bd67..3b06f9ca2638 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -39,7 +39,8 @@ static int __cmd_buildid_list(void)
39 int err = -1; 39 int err = -1;
40 struct perf_session *session; 40 struct perf_session *session;
41 41
42 session = perf_session__new(input_name, O_RDONLY, force, false); 42 session = perf_session__new(input_name, O_RDONLY, force, false,
43 &build_id__mark_dso_hit_ops);
43 if (session == NULL) 44 if (session == NULL)
44 return -1; 45 return -1;
45 46
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 5e1a043aae03..3153e492dbcc 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -61,6 +61,8 @@ static struct perf_event_ops event_ops = {
61 .exit = event__process_task, 61 .exit = event__process_task,
62 .fork = event__process_task, 62 .fork = event__process_task,
63 .lost = event__process_lost, 63 .lost = event__process_lost,
64 .ordered_samples = true,
65 .ordering_requires_timestamps = true,
64}; 66};
65 67
66static void perf_session__insert_hist_entry_by_name(struct rb_root *root, 68static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
@@ -142,8 +144,8 @@ static int __cmd_diff(void)
142 int ret, i; 144 int ret, i;
143 struct perf_session *session[2]; 145 struct perf_session *session[2];
144 146
145 session[0] = perf_session__new(input_old, O_RDONLY, force, false); 147 session[0] = perf_session__new(input_old, O_RDONLY, force, false, &event_ops);
146 session[1] = perf_session__new(input_new, O_RDONLY, force, false); 148 session[1] = perf_session__new(input_new, O_RDONLY, force, false, &event_ops);
147 if (session[0] == NULL || session[1] == NULL) 149 if (session[0] == NULL || session[1] == NULL)
148 return -ENOMEM; 150 return -ENOMEM;
149 151
@@ -192,6 +194,8 @@ static const struct option options[] = {
192 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator", 194 OPT_STRING('t', "field-separator", &symbol_conf.field_sep, "separator",
193 "separator for columns, no spaces will be added between " 195 "separator for columns, no spaces will be added between "
194 "columns '.' is reserved."), 196 "columns '.' is reserved."),
197 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
198 "Look for files with symbols relative to this directory"),
195 OPT_END() 199 OPT_END()
196}; 200};
197 201
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 4b66b8579410..0c78ffa7bf67 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -196,7 +196,7 @@ static int __cmd_inject(void)
196 inject_ops.tracing_data = event__repipe_tracing_data; 196 inject_ops.tracing_data = event__repipe_tracing_data;
197 } 197 }
198 198
199 session = perf_session__new(input_name, O_RDONLY, false, true); 199 session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops);
200 if (session == NULL) 200 if (session == NULL)
201 return -ENOMEM; 201 return -ENOMEM;
202 202
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index c9620ff6496f..def7ddc2fd4f 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -481,7 +481,8 @@ static void sort_result(void)
481static int __cmd_kmem(void) 481static int __cmd_kmem(void)
482{ 482{
483 int err = -EINVAL; 483 int err = -EINVAL;
484 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); 484 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
485 0, false, &event_ops);
485 if (session == NULL) 486 if (session == NULL)
486 return -ENOMEM; 487 return -ENOMEM;
487 488
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index b41b4492b1cc..b9c6e5432971 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -858,7 +858,7 @@ static struct perf_event_ops eops = {
858 858
859static int read_events(void) 859static int read_events(void)
860{ 860{
861 session = perf_session__new(input_name, O_RDONLY, 0, false); 861 session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
862 if (!session) 862 if (!session)
863 die("Initializing perf session failed\n"); 863 die("Initializing perf session failed\n");
864 864
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e9be6ae87a27..5149e3deb7bc 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -285,7 +285,7 @@ static void create_counter(int counter, int cpu)
285 if (system_wide) 285 if (system_wide)
286 attr->sample_type |= PERF_SAMPLE_CPU; 286 attr->sample_type |= PERF_SAMPLE_CPU;
287 287
288 if (sample_time) 288 if (sample_time || system_wide || !no_inherit || cpu_list)
289 attr->sample_type |= PERF_SAMPLE_TIME; 289 attr->sample_type |= PERF_SAMPLE_TIME;
290 290
291 if (raw_samples) { 291 if (raw_samples) {
@@ -327,6 +327,9 @@ try_again:
327 * Old kernel, no attr->sample_id_type_all field 327 * Old kernel, no attr->sample_id_type_all field
328 */ 328 */
329 sample_id_all_avail = false; 329 sample_id_all_avail = false;
330 if (!sample_time && !raw_samples)
331 attr->sample_type &= ~PERF_SAMPLE_TIME;
332
330 goto retry_sample_id; 333 goto retry_sample_id;
331 } 334 }
332 335
@@ -572,7 +575,7 @@ static int __cmd_record(int argc, const char **argv)
572 } 575 }
573 576
574 session = perf_session__new(output_name, O_WRONLY, 577 session = perf_session__new(output_name, O_WRONLY,
575 write_mode == WRITE_FORCE, false); 578 write_mode == WRITE_FORCE, false, NULL);
576 if (session == NULL) { 579 if (session == NULL) {
577 pr_err("Not enough memory for reading perf file header\n"); 580 pr_err("Not enough memory for reading perf file header\n");
578 return -1; 581 return -1;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index b6a2a899aa8f..75183a4518e6 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -244,6 +244,8 @@ static struct perf_event_ops event_ops = {
244 .event_type = event__process_event_type, 244 .event_type = event__process_event_type,
245 .tracing_data = event__process_tracing_data, 245 .tracing_data = event__process_tracing_data,
246 .build_id = event__process_build_id, 246 .build_id = event__process_build_id,
247 .ordered_samples = true,
248 .ordering_requires_timestamps = true,
247}; 249};
248 250
249extern volatile int session_done; 251extern volatile int session_done;
@@ -308,7 +310,7 @@ static int __cmd_report(void)
308 310
309 signal(SIGINT, sig_handler); 311 signal(SIGINT, sig_handler);
310 312
311 session = perf_session__new(input_name, O_RDONLY, force, false); 313 session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
312 if (session == NULL) 314 if (session == NULL)
313 return -ENOMEM; 315 return -ENOMEM;
314 316
@@ -481,6 +483,8 @@ static const struct option options[] = {
481 "columns '.' is reserved."), 483 "columns '.' is reserved."),
482 OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved, 484 OPT_BOOLEAN('U', "hide-unresolved", &hide_unresolved,
483 "Only display entries resolved to a symbol"), 485 "Only display entries resolved to a symbol"),
486 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
487 "Look for files with symbols relative to this directory"),
484 OPT_END() 488 OPT_END()
485}; 489};
486 490
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index c7753940aea0..7a4ebeb8b016 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1643,7 +1643,8 @@ static struct perf_event_ops event_ops = {
1643static int read_events(void) 1643static int read_events(void)
1644{ 1644{
1645 int err = -EINVAL; 1645 int err = -EINVAL;
1646 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); 1646 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
1647 0, false, &event_ops);
1647 if (session == NULL) 1648 if (session == NULL)
1648 return -ENOMEM; 1649 return -ENOMEM;
1649 1650
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 54f1ea808db5..6ef65c04ab9a 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -779,7 +779,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
779 if (!script_name) 779 if (!script_name)
780 setup_pager(); 780 setup_pager();
781 781
782 session = perf_session__new(input_name, O_RDONLY, 0, false); 782 session = perf_session__new(input_name, O_RDONLY, 0, false, &event_ops);
783 if (session == NULL) 783 if (session == NULL)
784 return -ENOMEM; 784 return -ENOMEM;
785 785
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index d2fc46103f83..d75084bccdb7 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -937,7 +937,8 @@ static struct perf_event_ops event_ops = {
937 937
938static int __cmd_timechart(void) 938static int __cmd_timechart(void)
939{ 939{
940 struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0, false); 940 struct perf_session *session = perf_session__new(input_name, O_RDONLY,
941 0, false, &event_ops);
941 int ret = -EINVAL; 942 int ret = -EINVAL;
942 943
943 if (session == NULL) 944 if (session == NULL)
@@ -1021,6 +1022,8 @@ static const struct option options[] = {
1021 OPT_CALLBACK('p', "process", NULL, "process", 1022 OPT_CALLBACK('p', "process", NULL, "process",
1022 "process selector. Pass a pid or process name.", 1023 "process selector. Pass a pid or process name.",
1023 parse_process), 1024 parse_process),
1025 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
1026 "Look for files with symbols relative to this directory"),
1024 OPT_END() 1027 OPT_END()
1025}; 1028};
1026 1029
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 0515ce9d3d3e..ae15f046c405 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1272,7 +1272,7 @@ static int __cmd_top(void)
1272 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this 1272 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
1273 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now. 1273 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
1274 */ 1274 */
1275 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false); 1275 struct perf_session *session = perf_session__new(NULL, O_WRONLY, false, false, NULL);
1276 if (session == NULL) 1276 if (session == NULL)
1277 return -ENOMEM; 1277 return -ENOMEM;
1278 1278
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index a3b84160c42e..d5036700a435 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1092,6 +1092,12 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
1092 FILE *file; 1092 FILE *file;
1093 int err = 0; 1093 int err = 0;
1094 u64 len; 1094 u64 len;
1095 char symfs_filename[PATH_MAX];
1096
1097 if (filename) {
1098 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
1099 symbol_conf.symfs, filename);
1100 }
1095 1101
1096 if (filename == NULL) { 1102 if (filename == NULL) {
1097 if (dso->has_build_id) { 1103 if (dso->has_build_id) {
@@ -1100,9 +1106,9 @@ int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
1100 return -ENOMEM; 1106 return -ENOMEM;
1101 } 1107 }
1102 goto fallback; 1108 goto fallback;
1103 } else if (readlink(filename, command, sizeof(command)) < 0 || 1109 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
1104 strstr(command, "[kernel.kallsyms]") || 1110 strstr(command, "[kernel.kallsyms]") ||
1105 access(filename, R_OK)) { 1111 access(symfs_filename, R_OK)) {
1106 free(filename); 1112 free(filename);
1107fallback: 1113fallback:
1108 /* 1114 /*
@@ -1111,6 +1117,8 @@ fallback:
1111 * DSO is the same as when 'perf record' ran. 1117 * DSO is the same as when 'perf record' ran.
1112 */ 1118 */
1113 filename = dso->long_name; 1119 filename = dso->long_name;
1120 snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
1121 symbol_conf.symfs, filename);
1114 free_filename = false; 1122 free_filename = false;
1115 } 1123 }
1116 1124
@@ -1137,7 +1145,7 @@ fallback:
1137 "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS -C %s|grep -v %s|expand", 1145 "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS -C %s|grep -v %s|expand",
1138 map__rip_2objdump(map, sym->start), 1146 map__rip_2objdump(map, sym->start),
1139 map__rip_2objdump(map, sym->end), 1147 map__rip_2objdump(map, sym->end),
1140 filename, filename); 1148 symfs_filename, filename);
1141 1149
1142 pr_debug("Executing: %s\n", command); 1150 pr_debug("Executing: %s\n", command);
1143 1151
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 3b6a5297bf16..099336ed34b4 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -95,7 +95,7 @@ static int init_vmlinux(void)
95 goto out; 95 goto out;
96 96
97 if (machine__create_kernel_maps(&machine) < 0) { 97 if (machine__create_kernel_maps(&machine) < 0) {
98 pr_debug("machine__create_kernel_maps "); 98 pr_debug("machine__create_kernel_maps() failed.\n");
99 goto out; 99 goto out;
100 } 100 }
101out: 101out:
@@ -140,7 +140,8 @@ static int open_vmlinux(const char *module)
140{ 140{
141 const char *path = kernel_get_module_path(module); 141 const char *path = kernel_get_module_path(module);
142 if (!path) { 142 if (!path) {
143 pr_err("Failed to find path of %s module", module ?: "kernel"); 143 pr_err("Failed to find path of %s module.\n",
144 module ?: "kernel");
144 return -ENOENT; 145 return -ENOENT;
145 } 146 }
146 pr_debug("Try to open %s\n", path); 147 pr_debug("Try to open %s\n", path);
@@ -217,7 +218,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
217 pr_warning("Warning: No dwarf info found in the vmlinux - " 218 pr_warning("Warning: No dwarf info found in the vmlinux - "
218 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 219 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
219 if (!need_dwarf) { 220 if (!need_dwarf) {
220 pr_debug("Trying to use symbols.\nn"); 221 pr_debug("Trying to use symbols.\n");
221 return 0; 222 return 0;
222 } 223 }
223 } 224 }
@@ -286,42 +287,49 @@ static int get_real_path(const char *raw_path, const char *comp_dir,
286#define LINEBUF_SIZE 256 287#define LINEBUF_SIZE 256
287#define NR_ADDITIONAL_LINES 2 288#define NR_ADDITIONAL_LINES 2
288 289
289static int show_one_line(FILE *fp, int l, bool skip, bool show_num) 290static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
290{ 291{
291 char buf[LINEBUF_SIZE]; 292 char buf[LINEBUF_SIZE];
292 const char *color = PERF_COLOR_BLUE; 293 const char *color = show_num ? "" : PERF_COLOR_BLUE;
294 const char *prefix = NULL;
293 295
294 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 296 do {
295 goto error;
296 if (!skip) {
297 if (show_num)
298 fprintf(stdout, "%7d %s", l, buf);
299 else
300 color_fprintf(stdout, color, " %s", buf);
301 }
302
303 while (strlen(buf) == LINEBUF_SIZE - 1 &&
304 buf[LINEBUF_SIZE - 2] != '\n') {
305 if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 297 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
306 goto error; 298 goto error;
307 if (!skip) { 299 if (skip)
308 if (show_num) 300 continue;
309 fprintf(stdout, "%s", buf); 301 if (!prefix) {
310 else 302 prefix = show_num ? "%7d " : " ";
311 color_fprintf(stdout, color, "%s", buf); 303 color_fprintf(stdout, color, prefix, l);
312 } 304 }
313 } 305 color_fprintf(stdout, color, "%s", buf);
314 306
315 return 0; 307 } while (strchr(buf, '\n') == NULL);
308
309 return 1;
316error: 310error:
317 if (feof(fp)) 311 if (ferror(fp)) {
318 pr_warning("Source file is shorter than expected.\n"); 312 pr_warning("Source file is shorter than expected.\n");
319 else 313 return -1;
320 pr_warning("File read error: %s\n", strerror(errno)); 314 }
315 return 0;
316}
321 317
322 return -1; 318static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
319{
320 int rv = __show_one_line(fp, l, skip, show_num);
321 if (rv == 0) {
322 pr_warning("Source file is shorter than expected.\n");
323 rv = -1;
324 }
325 return rv;
323} 326}
324 327
328#define show_one_line_with_num(f,l) _show_one_line(f,l,false,true)
329#define show_one_line(f,l) _show_one_line(f,l,false,false)
330#define skip_one_line(f,l) _show_one_line(f,l,true,false)
331#define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false)
332
325/* 333/*
326 * Show line-range always requires debuginfo to find source file and 334 * Show line-range always requires debuginfo to find source file and
327 * line number. 335 * line number.
@@ -370,7 +378,7 @@ int show_line_range(struct line_range *lr, const char *module)
370 fprintf(stdout, "<%s:%d>\n", lr->function, 378 fprintf(stdout, "<%s:%d>\n", lr->function,
371 lr->start - lr->offset); 379 lr->start - lr->offset);
372 else 380 else
373 fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); 381 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
374 382
375 fp = fopen(lr->path, "r"); 383 fp = fopen(lr->path, "r");
376 if (fp == NULL) { 384 if (fp == NULL) {
@@ -379,26 +387,30 @@ int show_line_range(struct line_range *lr, const char *module)
379 return -errno; 387 return -errno;
380 } 388 }
381 /* Skip to starting line number */ 389 /* Skip to starting line number */
382 while (l < lr->start && ret >= 0) 390 while (l < lr->start) {
383 ret = show_one_line(fp, l++, true, false); 391 ret = skip_one_line(fp, l++);
384 if (ret < 0) 392 if (ret < 0)
385 goto end; 393 goto end;
394 }
386 395
387 list_for_each_entry(ln, &lr->line_list, list) { 396 list_for_each_entry(ln, &lr->line_list, list) {
388 while (ln->line > l && ret >= 0) 397 for (; ln->line > l; l++) {
389 ret = show_one_line(fp, (l++) - lr->offset, 398 ret = show_one_line(fp, l - lr->offset);
390 false, false); 399 if (ret < 0)
391 if (ret >= 0) 400 goto end;
392 ret = show_one_line(fp, (l++) - lr->offset, 401 }
393 false, true); 402 ret = show_one_line_with_num(fp, l++ - lr->offset);
394 if (ret < 0) 403 if (ret < 0)
395 goto end; 404 goto end;
396 } 405 }
397 406
398 if (lr->end == INT_MAX) 407 if (lr->end == INT_MAX)
399 lr->end = l + NR_ADDITIONAL_LINES; 408 lr->end = l + NR_ADDITIONAL_LINES;
400 while (l <= lr->end && !feof(fp) && ret >= 0) 409 while (l <= lr->end) {
401 ret = show_one_line(fp, (l++) - lr->offset, false, false); 410 ret = show_one_line_or_eof(fp, l++ - lr->offset);
411 if (ret <= 0)
412 break;
413 }
402end: 414end:
403 fclose(fp); 415 fclose(fp);
404 return ret; 416 return ret;
@@ -457,7 +469,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
457 469
458 fd = open_vmlinux(module); 470 fd = open_vmlinux(module);
459 if (fd < 0) { 471 if (fd < 0) {
460 pr_warning("Failed to open debuginfo file.\n"); 472 pr_warning("Failed to open debug information file.\n");
461 return fd; 473 return fd;
462 } 474 }
463 475
@@ -517,56 +529,87 @@ int show_available_vars(struct perf_probe_event *pevs __unused,
517} 529}
518#endif 530#endif
519 531
532static int parse_line_num(char **ptr, int *val, const char *what)
533{
534 const char *start = *ptr;
535
536 errno = 0;
537 *val = strtol(*ptr, ptr, 0);
538 if (errno || *ptr == start) {
539 semantic_error("'%s' is not a valid number.\n", what);
540 return -EINVAL;
541 }
542 return 0;
543}
544
545/*
546 * Stuff 'lr' according to the line range described by 'arg'.
547 * The line range syntax is described by:
548 *
549 * SRC[:SLN[+NUM|-ELN]]
550 * FNC[:SLN[+NUM|-ELN]]
551 */
520int parse_line_range_desc(const char *arg, struct line_range *lr) 552int parse_line_range_desc(const char *arg, struct line_range *lr)
521{ 553{
522 const char *ptr; 554 char *range, *name = strdup(arg);
523 char *tmp; 555 int err;
524 /* 556
525 * <Syntax> 557 if (!name)
526 * SRC:SLN[+NUM|-ELN] 558 return -ENOMEM;
527 * FUNC[:SLN[+NUM|-ELN]] 559
528 */ 560 lr->start = 0;
529 ptr = strchr(arg, ':'); 561 lr->end = INT_MAX;
530 if (ptr) { 562
531 lr->start = (int)strtoul(ptr + 1, &tmp, 0); 563 range = strchr(name, ':');
532 if (*tmp == '+') { 564 if (range) {
533 lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); 565 *range++ = '\0';
534 lr->end--; /* 566
535 * Adjust the number of lines here. 567 err = parse_line_num(&range, &lr->start, "start line");
536 * If the number of lines == 1, the 568 if (err)
537 * the end of line should be equal to 569 goto err;
538 * the start of line. 570
539 */ 571 if (*range == '+' || *range == '-') {
540 } else if (*tmp == '-') 572 const char c = *range++;
541 lr->end = (int)strtoul(tmp + 1, &tmp, 0); 573
542 else 574 err = parse_line_num(&range, &lr->end, "end line");
543 lr->end = INT_MAX; 575 if (err)
576 goto err;
577
578 if (c == '+') {
579 lr->end += lr->start;
580 /*
581 * Adjust the number of lines here.
582 * If the number of lines == 1, the
583 * the end of line should be equal to
584 * the start of line.
585 */
586 lr->end--;
587 }
588 }
589
544 pr_debug("Line range is %d to %d\n", lr->start, lr->end); 590 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
591
592 err = -EINVAL;
545 if (lr->start > lr->end) { 593 if (lr->start > lr->end) {
546 semantic_error("Start line must be smaller" 594 semantic_error("Start line must be smaller"
547 " than end line.\n"); 595 " than end line.\n");
548 return -EINVAL; 596 goto err;
549 } 597 }
550 if (*tmp != '\0') { 598 if (*range != '\0') {
551 semantic_error("Tailing with invalid character '%d'.\n", 599 semantic_error("Tailing with invalid str '%s'.\n", range);
552 *tmp); 600 goto err;
553 return -EINVAL;
554 } 601 }
555 tmp = strndup(arg, (ptr - arg));
556 } else {
557 tmp = strdup(arg);
558 lr->end = INT_MAX;
559 } 602 }
560 603
561 if (tmp == NULL) 604 if (strchr(name, '.'))
562 return -ENOMEM; 605 lr->file = name;
563
564 if (strchr(tmp, '.'))
565 lr->file = tmp;
566 else 606 else
567 lr->function = tmp; 607 lr->function = name;
568 608
569 return 0; 609 return 0;
610err:
611 free(name);
612 return err;
570} 613}
571 614
572/* Check the name is good for event/group */ 615/* Check the name is good for event/group */
@@ -690,39 +733,40 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
690 733
691 /* Exclusion check */ 734 /* Exclusion check */
692 if (pp->lazy_line && pp->line) { 735 if (pp->lazy_line && pp->line) {
693 semantic_error("Lazy pattern can't be used with line number."); 736 semantic_error("Lazy pattern can't be used with"
737 " line number.\n");
694 return -EINVAL; 738 return -EINVAL;
695 } 739 }
696 740
697 if (pp->lazy_line && pp->offset) { 741 if (pp->lazy_line && pp->offset) {
698 semantic_error("Lazy pattern can't be used with offset."); 742 semantic_error("Lazy pattern can't be used with offset.\n");
699 return -EINVAL; 743 return -EINVAL;
700 } 744 }
701 745
702 if (pp->line && pp->offset) { 746 if (pp->line && pp->offset) {
703 semantic_error("Offset can't be used with line number."); 747 semantic_error("Offset can't be used with line number.\n");
704 return -EINVAL; 748 return -EINVAL;
705 } 749 }
706 750
707 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 751 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
708 semantic_error("File always requires line number or " 752 semantic_error("File always requires line number or "
709 "lazy pattern."); 753 "lazy pattern.\n");
710 return -EINVAL; 754 return -EINVAL;
711 } 755 }
712 756
713 if (pp->offset && !pp->function) { 757 if (pp->offset && !pp->function) {
714 semantic_error("Offset requires an entry function."); 758 semantic_error("Offset requires an entry function.\n");
715 return -EINVAL; 759 return -EINVAL;
716 } 760 }
717 761
718 if (pp->retprobe && !pp->function) { 762 if (pp->retprobe && !pp->function) {
719 semantic_error("Return probe requires an entry function."); 763 semantic_error("Return probe requires an entry function.\n");
720 return -EINVAL; 764 return -EINVAL;
721 } 765 }
722 766
723 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 767 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
724 semantic_error("Offset/Line/Lazy pattern can't be used with " 768 semantic_error("Offset/Line/Lazy pattern can't be used with "
725 "return probe."); 769 "return probe.\n");
726 return -EINVAL; 770 return -EINVAL;
727 } 771 }
728 772
@@ -996,7 +1040,7 @@ int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
996 1040
997 return tmp - buf; 1041 return tmp - buf;
998error: 1042error:
999 pr_debug("Failed to synthesize perf probe argument: %s", 1043 pr_debug("Failed to synthesize perf probe argument: %s\n",
1000 strerror(-ret)); 1044 strerror(-ret));
1001 return ret; 1045 return ret;
1002} 1046}
@@ -1046,7 +1090,7 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1046 1090
1047 return buf; 1091 return buf;
1048error: 1092error:
1049 pr_debug("Failed to synthesize perf probe point: %s", 1093 pr_debug("Failed to synthesize perf probe point: %s\n",
1050 strerror(-ret)); 1094 strerror(-ret));
1051 if (buf) 1095 if (buf)
1052 free(buf); 1096 free(buf);
@@ -1787,7 +1831,7 @@ static int del_trace_probe_event(int fd, const char *group,
1787 1831
1788 ret = e_snprintf(buf, 128, "%s:%s", group, event); 1832 ret = e_snprintf(buf, 128, "%s:%s", group, event);
1789 if (ret < 0) { 1833 if (ret < 0) {
1790 pr_err("Failed to copy event."); 1834 pr_err("Failed to copy event.\n");
1791 return ret; 1835 return ret;
1792 } 1836 }
1793 1837
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 3991d73d1cff..90b629226bd7 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -627,8 +627,8 @@ static_var:
627 regs = get_arch_regstr(regn); 627 regs = get_arch_regstr(regn);
628 if (!regs) { 628 if (!regs) {
629 /* This should be a bug in DWARF or this tool */ 629 /* This should be a bug in DWARF or this tool */
630 pr_warning("Mapping for DWARF register number %u " 630 pr_warning("Mapping for the register number %u "
631 "missing on this architecture.", regn); 631 "missing on this architecture.\n", regn);
632 return -ERANGE; 632 return -ERANGE;
633 } 633 }
634 634
@@ -674,13 +674,14 @@ static int convert_variable_type(Dwarf_Die *vr_die,
674 if (ret != DW_TAG_pointer_type && 674 if (ret != DW_TAG_pointer_type &&
675 ret != DW_TAG_array_type) { 675 ret != DW_TAG_array_type) {
676 pr_warning("Failed to cast into string: " 676 pr_warning("Failed to cast into string: "
677 "%s(%s) is not a pointer nor array.", 677 "%s(%s) is not a pointer nor array.\n",
678 dwarf_diename(vr_die), dwarf_diename(&type)); 678 dwarf_diename(vr_die), dwarf_diename(&type));
679 return -EINVAL; 679 return -EINVAL;
680 } 680 }
681 if (ret == DW_TAG_pointer_type) { 681 if (ret == DW_TAG_pointer_type) {
682 if (die_get_real_type(&type, &type) == NULL) { 682 if (die_get_real_type(&type, &type) == NULL) {
683 pr_warning("Failed to get a type information."); 683 pr_warning("Failed to get a type"
684 " information.\n");
684 return -ENOENT; 685 return -ENOENT;
685 } 686 }
686 while (*ref_ptr) 687 while (*ref_ptr)
@@ -695,7 +696,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
695 if (!die_compare_name(&type, "char") && 696 if (!die_compare_name(&type, "char") &&
696 !die_compare_name(&type, "unsigned char")) { 697 !die_compare_name(&type, "unsigned char")) {
697 pr_warning("Failed to cast into string: " 698 pr_warning("Failed to cast into string: "
698 "%s is not (unsigned) char *.", 699 "%s is not (unsigned) char *.\n",
699 dwarf_diename(vr_die)); 700 dwarf_diename(vr_die));
700 return -EINVAL; 701 return -EINVAL;
701 } 702 }
@@ -805,8 +806,8 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
805 return -EINVAL; 806 return -EINVAL;
806 } 807 }
807 if (field->name[0] == '[') { 808 if (field->name[0] == '[') {
808 pr_err("Semantic error: %s is not a pointor nor array.", 809 pr_err("Semantic error: %s is not a pointor"
809 varname); 810 " nor array.\n", varname);
810 return -EINVAL; 811 return -EINVAL;
811 } 812 }
812 if (field->ref) { 813 if (field->ref) {
@@ -953,7 +954,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
953 name = dwarf_diename(sp_die); 954 name = dwarf_diename(sp_die);
954 if (name) { 955 if (name) {
955 if (dwarf_entrypc(sp_die, &eaddr) != 0) { 956 if (dwarf_entrypc(sp_die, &eaddr) != 0) {
956 pr_warning("Failed to get entry pc of %s\n", 957 pr_warning("Failed to get entry address of %s\n",
957 dwarf_diename(sp_die)); 958 dwarf_diename(sp_die));
958 return -ENOENT; 959 return -ENOENT;
959 } 960 }
@@ -969,7 +970,7 @@ static int convert_to_trace_point(Dwarf_Die *sp_die, Dwarf_Addr paddr,
969 if (retprobe) { 970 if (retprobe) {
970 if (eaddr != paddr) { 971 if (eaddr != paddr) {
971 pr_warning("Return probe must be on the head of" 972 pr_warning("Return probe must be on the head of"
972 " a real function\n"); 973 " a real function.\n");
973 return -EINVAL; 974 return -EINVAL;
974 } 975 }
975 tp->retprobe = true; 976 tp->retprobe = true;
@@ -1008,7 +1009,7 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
1008 Dwarf_Frame *frame; 1009 Dwarf_Frame *frame;
1009 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || 1010 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 ||
1010 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { 1011 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) {
1011 pr_warning("Failed to get CFA on 0x%jx\n", 1012 pr_warning("Failed to get call frame on 0x%jx\n",
1012 (uintmax_t)pf->addr); 1013 (uintmax_t)pf->addr);
1013 return -ENOENT; 1014 return -ENOENT;
1014 } 1015 }
@@ -1035,7 +1036,7 @@ static int find_probe_point_by_line(struct probe_finder *pf)
1035 int ret = 0; 1036 int ret = 0;
1036 1037
1037 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 1038 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1038 pr_warning("No source lines found in this CU.\n"); 1039 pr_warning("No source lines found.\n");
1039 return -ENOENT; 1040 return -ENOENT;
1040 } 1041 }
1041 1042
@@ -1137,7 +1138,7 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
1137 } 1138 }
1138 1139
1139 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 1140 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
1140 pr_warning("No source lines found in this CU.\n"); 1141 pr_warning("No source lines found.\n");
1141 return -ENOENT; 1142 return -ENOENT;
1142 } 1143 }
1143 1144
@@ -1195,7 +1196,7 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
1195 else { 1196 else {
1196 /* Get probe address */ 1197 /* Get probe address */
1197 if (dwarf_entrypc(in_die, &addr) != 0) { 1198 if (dwarf_entrypc(in_die, &addr) != 0) {
1198 pr_warning("Failed to get entry pc of %s.\n", 1199 pr_warning("Failed to get entry address of %s.\n",
1199 dwarf_diename(in_die)); 1200 dwarf_diename(in_die));
1200 param->retval = -ENOENT; 1201 param->retval = -ENOENT;
1201 return DWARF_CB_ABORT; 1202 return DWARF_CB_ABORT;
@@ -1236,8 +1237,8 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1236 param->retval = find_probe_point_lazy(sp_die, pf); 1237 param->retval = find_probe_point_lazy(sp_die, pf);
1237 else { 1238 else {
1238 if (dwarf_entrypc(sp_die, &pf->addr) != 0) { 1239 if (dwarf_entrypc(sp_die, &pf->addr) != 0) {
1239 pr_warning("Failed to get entry pc of %s.\n", 1240 pr_warning("Failed to get entry address of "
1240 dwarf_diename(sp_die)); 1241 "%s.\n", dwarf_diename(sp_die));
1241 param->retval = -ENOENT; 1242 param->retval = -ENOENT;
1242 return DWARF_CB_ABORT; 1243 return DWARF_CB_ABORT;
1243 } 1244 }
@@ -1279,7 +1280,7 @@ static int find_probes(int fd, struct probe_finder *pf)
1279 1280
1280 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); 1281 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1281 if (!dbg) { 1282 if (!dbg) {
1282 pr_warning("No dwarf info found in the vmlinux - " 1283 pr_warning("No debug information found in the vmlinux - "
1283 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1284 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1284 return -EBADF; 1285 return -EBADF;
1285 } 1286 }
@@ -1524,7 +1525,7 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1524 /* Open the live linux kernel */ 1525 /* Open the live linux kernel */
1525 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); 1526 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
1526 if (!dbg) { 1527 if (!dbg) {
1527 pr_warning("No dwarf info found in the vmlinux - " 1528 pr_warning("No debug information found in the vmlinux - "
1528 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1529 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1529 ret = -EINVAL; 1530 ret = -EINVAL;
1530 goto end; 1531 goto end;
@@ -1534,7 +1535,8 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1534 addr += bias; 1535 addr += bias;
1535 /* Find cu die */ 1536 /* Find cu die */
1536 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) { 1537 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr - bias, &cudie)) {
1537 pr_warning("No CU DIE is found at %lx\n", addr); 1538 pr_warning("Failed to find debug information for address %lx\n",
1539 addr);
1538 ret = -EINVAL; 1540 ret = -EINVAL;
1539 goto end; 1541 goto end;
1540 } 1542 }
@@ -1659,7 +1661,7 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
1659 1661
1660 line_list__init(&lf->lr->line_list); 1662 line_list__init(&lf->lr->line_list);
1661 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) { 1663 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
1662 pr_warning("No source lines found in this CU.\n"); 1664 pr_warning("No source lines found.\n");
1663 return -ENOENT; 1665 return -ENOENT;
1664 } 1666 }
1665 1667
@@ -1784,7 +1786,7 @@ int find_line_range(int fd, struct line_range *lr)
1784 1786
1785 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias); 1787 dbg = dwfl_init_offline_dwarf(fd, &dwfl, &bias);
1786 if (!dbg) { 1788 if (!dbg) {
1787 pr_warning("No dwarf info found in the vmlinux - " 1789 pr_warning("No debug information found in the vmlinux - "
1788 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1790 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1789 return -EBADF; 1791 return -EBADF;
1790 } 1792 }
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index b59abf5aba36..0f7e544544f5 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -125,7 +125,9 @@ static void perf_session__destroy_kernel_maps(struct perf_session *self)
125 machines__destroy_guest_kernel_maps(&self->machines); 125 machines__destroy_guest_kernel_maps(&self->machines);
126} 126}
127 127
128struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) 128struct perf_session *perf_session__new(const char *filename, int mode,
129 bool force, bool repipe,
130 struct perf_event_ops *ops)
129{ 131{
130 size_t len = filename ? strlen(filename) + 1 : 0; 132 size_t len = filename ? strlen(filename) + 1 : 0;
131 struct perf_session *self = zalloc(sizeof(*self) + len); 133 struct perf_session *self = zalloc(sizeof(*self) + len);
@@ -170,6 +172,13 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
170 } 172 }
171 173
172 perf_session__update_sample_type(self); 174 perf_session__update_sample_type(self);
175
176 if (ops && ops->ordering_requires_timestamps &&
177 ops->ordered_samples && !self->sample_id_all) {
178 dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
179 ops->ordered_samples = false;
180 }
181
173out: 182out:
174 return self; 183 return self;
175out_free: 184out_free:
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index ac36f99f14af..ffe4b98db8f0 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -78,9 +78,12 @@ struct perf_event_ops {
78 build_id; 78 build_id;
79 event_op2 finished_round; 79 event_op2 finished_round;
80 bool ordered_samples; 80 bool ordered_samples;
81 bool ordering_requires_timestamps;
81}; 82};
82 83
83struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe); 84struct perf_session *perf_session__new(const char *filename, int mode,
85 bool force, bool repipe,
86 struct perf_event_ops *ops);
84void perf_session__delete(struct perf_session *self); 87void perf_session__delete(struct perf_session *self);
85 88
86void perf_event_header__bswap(struct perf_event_header *self); 89void perf_event_header__bswap(struct perf_event_header *self);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index ceefa6568def..561db6361f57 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -41,6 +41,7 @@ struct symbol_conf symbol_conf = {
41 .exclude_other = true, 41 .exclude_other = true,
42 .use_modules = true, 42 .use_modules = true,
43 .try_vmlinux_path = true, 43 .try_vmlinux_path = true,
44 .symfs = "",
44}; 45};
45 46
46int dso__name_len(const struct dso *self) 47int dso__name_len(const struct dso *self)
@@ -839,8 +840,11 @@ static int dso__synthesize_plt_symbols(struct dso *self, struct map *map,
839 char sympltname[1024]; 840 char sympltname[1024];
840 Elf *elf; 841 Elf *elf;
841 int nr = 0, symidx, fd, err = 0; 842 int nr = 0, symidx, fd, err = 0;
843 char name[PATH_MAX];
842 844
843 fd = open(self->long_name, O_RDONLY); 845 snprintf(name, sizeof(name), "%s%s",
846 symbol_conf.symfs, self->long_name);
847 fd = open(name, O_RDONLY);
844 if (fd < 0) 848 if (fd < 0)
845 goto out; 849 goto out;
846 850
@@ -1452,16 +1456,19 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1452 self->origin++) { 1456 self->origin++) {
1453 switch (self->origin) { 1457 switch (self->origin) {
1454 case DSO__ORIG_BUILD_ID_CACHE: 1458 case DSO__ORIG_BUILD_ID_CACHE:
1455 if (dso__build_id_filename(self, name, size) == NULL) 1459 /* skip the locally configured cache if a symfs is given */
1460 if (symbol_conf.symfs[0] ||
1461 (dso__build_id_filename(self, name, size) == NULL)) {
1456 continue; 1462 continue;
1463 }
1457 break; 1464 break;
1458 case DSO__ORIG_FEDORA: 1465 case DSO__ORIG_FEDORA:
1459 snprintf(name, size, "/usr/lib/debug%s.debug", 1466 snprintf(name, size, "%s/usr/lib/debug%s.debug",
1460 self->long_name); 1467 symbol_conf.symfs, self->long_name);
1461 break; 1468 break;
1462 case DSO__ORIG_UBUNTU: 1469 case DSO__ORIG_UBUNTU:
1463 snprintf(name, size, "/usr/lib/debug%s", 1470 snprintf(name, size, "%s/usr/lib/debug%s",
1464 self->long_name); 1471 symbol_conf.symfs, self->long_name);
1465 break; 1472 break;
1466 case DSO__ORIG_BUILDID: { 1473 case DSO__ORIG_BUILDID: {
1467 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 1474 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
@@ -1473,19 +1480,26 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1473 sizeof(self->build_id), 1480 sizeof(self->build_id),
1474 build_id_hex); 1481 build_id_hex);
1475 snprintf(name, size, 1482 snprintf(name, size,
1476 "/usr/lib/debug/.build-id/%.2s/%s.debug", 1483 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
1477 build_id_hex, build_id_hex + 2); 1484 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
1478 } 1485 }
1479 break; 1486 break;
1480 case DSO__ORIG_DSO: 1487 case DSO__ORIG_DSO:
1481 snprintf(name, size, "%s", self->long_name); 1488 snprintf(name, size, "%s%s",
1489 symbol_conf.symfs, self->long_name);
1482 break; 1490 break;
1483 case DSO__ORIG_GUEST_KMODULE: 1491 case DSO__ORIG_GUEST_KMODULE:
1484 if (map->groups && map->groups->machine) 1492 if (map->groups && map->groups->machine)
1485 root_dir = map->groups->machine->root_dir; 1493 root_dir = map->groups->machine->root_dir;
1486 else 1494 else
1487 root_dir = ""; 1495 root_dir = "";
1488 snprintf(name, size, "%s%s", root_dir, self->long_name); 1496 snprintf(name, size, "%s%s%s", symbol_conf.symfs,
1497 root_dir, self->long_name);
1498 break;
1499
1500 case DSO__ORIG_KMODULE:
1501 snprintf(name, size, "%s%s", symbol_conf.symfs,
1502 self->long_name);
1489 break; 1503 break;
1490 1504
1491 default: 1505 default:
@@ -1784,17 +1798,20 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,
1784 const char *vmlinux, symbol_filter_t filter) 1798 const char *vmlinux, symbol_filter_t filter)
1785{ 1799{
1786 int err = -1, fd; 1800 int err = -1, fd;
1801 char symfs_vmlinux[PATH_MAX];
1787 1802
1788 fd = open(vmlinux, O_RDONLY); 1803 snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s/%s",
1804 symbol_conf.symfs, vmlinux);
1805 fd = open(symfs_vmlinux, O_RDONLY);
1789 if (fd < 0) 1806 if (fd < 0)
1790 return -1; 1807 return -1;
1791 1808
1792 dso__set_loaded(self, map->type); 1809 dso__set_loaded(self, map->type);
1793 err = dso__load_sym(self, map, vmlinux, fd, filter, 0, 0); 1810 err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0);
1794 close(fd); 1811 close(fd);
1795 1812
1796 if (err > 0) 1813 if (err > 0)
1797 pr_debug("Using %s for symbols\n", vmlinux); 1814 pr_debug("Using %s for symbols\n", symfs_vmlinux);
1798 1815
1799 return err; 1816 return err;
1800} 1817}
@@ -1872,6 +1889,10 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1872 goto out_fixup; 1889 goto out_fixup;
1873 } 1890 }
1874 1891
1892 /* do not try local files if a symfs was given */
1893 if (symbol_conf.symfs[0] != 0)
1894 return -1;
1895
1875 /* 1896 /*
1876 * Say the kernel DSO was created when processing the build-id header table, 1897 * Say the kernel DSO was created when processing the build-id header table,
1877 * we have a build-id, so check if it is the same as the running kernel, 1898 * we have a build-id, so check if it is the same as the running kernel,
@@ -2262,9 +2283,6 @@ static int vmlinux_path__init(void)
2262 struct utsname uts; 2283 struct utsname uts;
2263 char bf[PATH_MAX]; 2284 char bf[PATH_MAX];
2264 2285
2265 if (uname(&uts) < 0)
2266 return -1;
2267
2268 vmlinux_path = malloc(sizeof(char *) * 5); 2286 vmlinux_path = malloc(sizeof(char *) * 5);
2269 if (vmlinux_path == NULL) 2287 if (vmlinux_path == NULL)
2270 return -1; 2288 return -1;
@@ -2277,6 +2295,14 @@ static int vmlinux_path__init(void)
2277 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2295 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
2278 goto out_fail; 2296 goto out_fail;
2279 ++vmlinux_path__nr_entries; 2297 ++vmlinux_path__nr_entries;
2298
2299 /* only try running kernel version if no symfs was given */
2300 if (symbol_conf.symfs[0] != 0)
2301 return 0;
2302
2303 if (uname(&uts) < 0)
2304 return -1;
2305
2280 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release); 2306 snprintf(bf, sizeof(bf), "/boot/vmlinux-%s", uts.release);
2281 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf); 2307 vmlinux_path[vmlinux_path__nr_entries] = strdup(bf);
2282 if (vmlinux_path[vmlinux_path__nr_entries] == NULL) 2308 if (vmlinux_path[vmlinux_path__nr_entries] == NULL)
@@ -2336,6 +2362,8 @@ static int setup_list(struct strlist **list, const char *list_str,
2336 2362
2337int symbol__init(void) 2363int symbol__init(void)
2338{ 2364{
2365 const char *symfs;
2366
2339 if (symbol_conf.initialized) 2367 if (symbol_conf.initialized)
2340 return 0; 2368 return 0;
2341 2369
@@ -2364,6 +2392,18 @@ int symbol__init(void)
2364 symbol_conf.sym_list_str, "symbol") < 0) 2392 symbol_conf.sym_list_str, "symbol") < 0)
2365 goto out_free_comm_list; 2393 goto out_free_comm_list;
2366 2394
2395 /*
2396 * A path to symbols of "/" is identical to ""
2397 * reset here for simplicity.
2398 */
2399 symfs = realpath(symbol_conf.symfs, NULL);
2400 if (symfs == NULL)
2401 symfs = symbol_conf.symfs;
2402 if (strcmp(symfs, "/") == 0)
2403 symbol_conf.symfs = "";
2404 if (symfs != symbol_conf.symfs)
2405 free((void *)symfs);
2406
2367 symbol_conf.initialized = true; 2407 symbol_conf.initialized = true;
2368 return 0; 2408 return 0;
2369 2409
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 12defbe18c13..bcd2f986927e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -86,6 +86,7 @@ struct symbol_conf {
86 struct strlist *dso_list, 86 struct strlist *dso_list,
87 *comm_list, 87 *comm_list,
88 *sym_list; 88 *sym_list;
89 const char *symfs;
89}; 90};
90 91
91extern struct symbol_conf symbol_conf; 92extern struct symbol_conf symbol_conf;