diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-12-22 05:54:50 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-12-22 05:54:50 -0500 |
commit | 8c1df4002aa425973d7d25ffa56c042acd953bed (patch) | |
tree | 441e39bf3a43bb3e4c4965ed2081b9bb90edd1ea | |
parent | 6c529a266bdc590a870ee2d2092ff6527eff427b (diff) | |
parent | 21dd9ae5a4e9f717f3957ec934dd3158129436b8 (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.txt | 2 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-probe.txt | 2 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-report.txt | 3 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-timechart.txt | 2 | ||||
-rw-r--r-- | tools/perf/builtin-annotate.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-buildid-list.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-diff.c | 8 | ||||
-rw-r--r-- | tools/perf/builtin-inject.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-kmem.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-lock.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 7 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 6 | ||||
-rw-r--r-- | tools/perf/builtin-sched.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-script.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-timechart.c | 5 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 2 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 14 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 220 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 42 | ||||
-rw-r--r-- | tools/perf/util/session.c | 11 | ||||
-rw-r--r-- | tools/perf/util/session.h | 5 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 72 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 1 |
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 | ||
70 | SEE ALSO | 72 | SEE 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 | ----------- |
118 | Line range is described by following syntax. | 118 | Line 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 | ||
122 | FUNC specifies the function name of showing lines. 'RLN' is the start line | 122 | FUNC specifies the function name of showing lines. 'RLN' is the start line |
123 | number from function entry line, and 'RLN2' is the end line number. As same as | 123 | number 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 | |||
119 | SEE ALSO | 122 | SEE ALSO |
120 | -------- | 123 | -------- |
121 | linkperf:perf-stat[1] | 124 | linkperf: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 | ||
42 | SEE ALSO | 44 | SEE 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 | ||
380 | static int __cmd_annotate(void) | 382 | static 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 | ||
66 | static void perf_session__insert_hist_entry_by_name(struct rb_root *root, | 68 | static 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) | |||
481 | static int __cmd_kmem(void) | 481 | static 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 | ||
859 | static int read_events(void) | 859 | static 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 | ||
249 | extern volatile int session_done; | 251 | extern 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 = { | |||
1643 | static int read_events(void) | 1643 | static 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 | ||
938 | static int __cmd_timechart(void) | 938 | static 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); |
1107 | fallback: | 1113 | fallback: |
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 | } |
101 | out: | 101 | out: |
@@ -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 | ||
289 | static int show_one_line(FILE *fp, int l, bool skip, bool show_num) | 290 | static 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; | ||
316 | error: | 310 | error: |
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; | 318 | static 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 | } | ||
402 | end: | 414 | end: |
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 | ||
532 | static 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 | */ | ||
520 | int parse_line_range_desc(const char *arg, struct line_range *lr) | 552 | int 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; |
610 | err: | ||
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; |
998 | error: | 1042 | error: |
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; |
1048 | error: | 1092 | error: |
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 | ||
128 | struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe) | 128 | struct 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 | |||
173 | out: | 182 | out: |
174 | return self; | 183 | return self; |
175 | out_free: | 184 | out_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 | ||
83 | struct perf_session *perf_session__new(const char *filename, int mode, bool force, bool repipe); | 84 | struct perf_session *perf_session__new(const char *filename, int mode, |
85 | bool force, bool repipe, | ||
86 | struct perf_event_ops *ops); | ||
84 | void perf_session__delete(struct perf_session *self); | 87 | void perf_session__delete(struct perf_session *self); |
85 | 88 | ||
86 | void perf_event_header__bswap(struct perf_event_header *self); | 89 | void 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 | ||
46 | int dso__name_len(const struct dso *self) | 47 | int 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 | ||
2337 | int symbol__init(void) | 2363 | int 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 | ||
91 | extern struct symbol_conf symbol_conf; | 92 | extern struct symbol_conf symbol_conf; |