diff options
| -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; |
