diff options
| author | Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> | 2011-01-13 07:46:11 -0500 |
|---|---|---|
| committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2011-01-24 07:57:55 -0500 |
| commit | e80711ca8512c8586da0c3e18e2f1caf73c88731 (patch) | |
| tree | 2b6493cd34b5a68ec9008c34a47f8f145711132f | |
| parent | 5069ed86be3c2f28bcdf7fae1374ec0c325aafba (diff) | |
perf probe: Add --funcs to show available functions in symtab
Add --funcs to show available functions in symtab.
Originally this feature came from Srikar's uprobes patches
( http://lkml.org/lkml/2010/8/27/244 )
e.g.
...
__ablkcipher_walk_complete
__absent_pages_in_range
__account_scheduler_latency
__add_pages
__alloc_pages_nodemask
__alloc_percpu
__alloc_reserved_percpu
__alloc_skb
__alloc_workqueue_key
__any_online_cpu
__ata_ehi_push_desc
...
This also supports symbols in module, e.g.
...
cleanup_module
cpuid_maxphyaddr
emulate_clts
emulate_instruction
emulate_int_real
emulate_invlpg
emulator_get_dr
emulator_set_dr
emulator_task_switch
emulator_write_emulated
emulator_write_phys
fx_init
...
Original-patch-from: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: 2nddept-manager@sdl.hitachi.co.jp
Cc: Franck Bui-Huu <fbuihuu@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
LKML-Reference: <20110113124611.22426.10835.stgit@ltc236.sdl.hitachi.co.jp>
Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
[ committer note: Add missing elf.h for STB_GLOBAL that broke a RHEL4 build ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
| -rw-r--r-- | tools/perf/Documentation/perf-probe.txt | 4 | ||||
| -rw-r--r-- | tools/perf/builtin-probe.c | 29 | ||||
| -rw-r--r-- | tools/perf/util/probe-event.c | 68 | ||||
| -rw-r--r-- | tools/perf/util/probe-event.h | 1 |
4 files changed, 99 insertions, 3 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 86b797a35aa6..fcc51fe0195c 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt | |||
| @@ -73,6 +73,10 @@ OPTIONS | |||
| 73 | (Only for --vars) Show external defined variables in addition to local | 73 | (Only for --vars) Show external defined variables in addition to local |
| 74 | variables. | 74 | variables. |
| 75 | 75 | ||
| 76 | -F:: | ||
| 77 | --funcs:: | ||
| 78 | Show available functions in given module or kernel. | ||
| 79 | |||
| 76 | -f:: | 80 | -f:: |
| 77 | --force:: | 81 | --force:: |
| 78 | Forcibly add events with existing name. | 82 | Forcibly add events with existing name. |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index add163c9f0e7..6cf708aba7c9 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
| @@ -52,6 +52,7 @@ static struct { | |||
| 52 | bool show_lines; | 52 | bool show_lines; |
| 53 | bool show_vars; | 53 | bool show_vars; |
| 54 | bool show_ext_vars; | 54 | bool show_ext_vars; |
| 55 | bool show_funcs; | ||
| 55 | bool mod_events; | 56 | bool mod_events; |
| 56 | int nevents; | 57 | int nevents; |
| 57 | struct perf_probe_event events[MAX_PROBES]; | 58 | struct perf_probe_event events[MAX_PROBES]; |
| @@ -221,6 +222,8 @@ static const struct option options[] = { | |||
| 221 | OPT__DRY_RUN(&probe_event_dry_run), | 222 | OPT__DRY_RUN(&probe_event_dry_run), |
| 222 | OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, | 223 | OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, |
| 223 | "Set how many probe points can be found for a probe."), | 224 | "Set how many probe points can be found for a probe."), |
| 225 | OPT_BOOLEAN('F', "funcs", ¶ms.show_funcs, | ||
| 226 | "Show potential probe-able functions."), | ||
| 224 | OPT_END() | 227 | OPT_END() |
| 225 | }; | 228 | }; |
| 226 | 229 | ||
| @@ -246,7 +249,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
| 246 | params.max_probe_points = MAX_PROBES; | 249 | params.max_probe_points = MAX_PROBES; |
| 247 | 250 | ||
| 248 | if ((!params.nevents && !params.dellist && !params.list_events && | 251 | if ((!params.nevents && !params.dellist && !params.list_events && |
| 249 | !params.show_lines)) | 252 | !params.show_lines && !params.show_funcs)) |
| 250 | usage_with_options(probe_usage, options); | 253 | usage_with_options(probe_usage, options); |
| 251 | 254 | ||
| 252 | /* | 255 | /* |
| @@ -267,12 +270,36 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
| 267 | pr_err(" Error: Don't use --list with --vars.\n"); | 270 | pr_err(" Error: Don't use --list with --vars.\n"); |
| 268 | usage_with_options(probe_usage, options); | 271 | usage_with_options(probe_usage, options); |
| 269 | } | 272 | } |
| 273 | if (params.show_funcs) { | ||
| 274 | pr_err(" Error: Don't use --list with --funcs.\n"); | ||
| 275 | usage_with_options(probe_usage, options); | ||
| 276 | } | ||
| 270 | ret = show_perf_probe_events(); | 277 | ret = show_perf_probe_events(); |
| 271 | if (ret < 0) | 278 | if (ret < 0) |
| 272 | pr_err(" Error: Failed to show event list. (%d)\n", | 279 | pr_err(" Error: Failed to show event list. (%d)\n", |
| 273 | ret); | 280 | ret); |
| 274 | return ret; | 281 | return ret; |
| 275 | } | 282 | } |
| 283 | if (params.show_funcs) { | ||
| 284 | if (params.nevents != 0 || params.dellist) { | ||
| 285 | pr_err(" Error: Don't use --funcs with" | ||
| 286 | " --add/--del.\n"); | ||
| 287 | usage_with_options(probe_usage, options); | ||
| 288 | } | ||
| 289 | if (params.show_lines) { | ||
| 290 | pr_err(" Error: Don't use --funcs with --line.\n"); | ||
| 291 | usage_with_options(probe_usage, options); | ||
| 292 | } | ||
| 293 | if (params.show_vars) { | ||
| 294 | pr_err(" Error: Don't use --funcs with --vars.\n"); | ||
| 295 | usage_with_options(probe_usage, options); | ||
| 296 | } | ||
| 297 | ret = show_available_funcs(params.target_module); | ||
| 298 | if (ret < 0) | ||
| 299 | pr_err(" Error: Failed to show functions." | ||
| 300 | " (%d)\n", ret); | ||
| 301 | return ret; | ||
| 302 | } | ||
| 276 | 303 | ||
| 277 | #ifdef DWARF_SUPPORT | 304 | #ifdef DWARF_SUPPORT |
| 278 | if (params.show_lines) { | 305 | if (params.show_lines) { |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 6e29d9c9dccc..859d377a3df3 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <string.h> | 31 | #include <string.h> |
| 32 | #include <stdarg.h> | 32 | #include <stdarg.h> |
| 33 | #include <limits.h> | 33 | #include <limits.h> |
| 34 | #include <elf.h> | ||
| 34 | 35 | ||
| 35 | #undef _GNU_SOURCE | 36 | #undef _GNU_SOURCE |
| 36 | #include "util.h" | 37 | #include "util.h" |
| @@ -111,7 +112,25 @@ static struct symbol *__find_kernel_function_by_name(const char *name, | |||
| 111 | NULL); | 112 | NULL); |
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | const char *kernel_get_module_path(const char *module) | 115 | static struct map *kernel_get_module_map(const char *module) |
| 116 | { | ||
| 117 | struct rb_node *nd; | ||
| 118 | struct map_groups *grp = &machine.kmaps; | ||
| 119 | |||
| 120 | if (!module) | ||
| 121 | module = "kernel"; | ||
| 122 | |||
| 123 | for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { | ||
| 124 | struct map *pos = rb_entry(nd, struct map, rb_node); | ||
| 125 | if (strncmp(pos->dso->short_name + 1, module, | ||
| 126 | pos->dso->short_name_len - 2) == 0) { | ||
| 127 | return pos; | ||
| 128 | } | ||
| 129 | } | ||
| 130 | return NULL; | ||
| 131 | } | ||
| 132 | |||
| 133 | static struct dso *kernel_get_module_dso(const char *module) | ||
| 115 | { | 134 | { |
| 116 | struct dso *dso; | 135 | struct dso *dso; |
| 117 | struct map *map; | 136 | struct map *map; |
| @@ -141,7 +160,13 @@ const char *kernel_get_module_path(const char *module) | |||
| 141 | } | 160 | } |
| 142 | } | 161 | } |
| 143 | found: | 162 | found: |
| 144 | return dso->long_name; | 163 | return dso; |
| 164 | } | ||
| 165 | |||
| 166 | const char *kernel_get_module_path(const char *module) | ||
| 167 | { | ||
| 168 | struct dso *dso = kernel_get_module_dso(module); | ||
| 169 | return (dso) ? dso->long_name : NULL; | ||
| 145 | } | 170 | } |
| 146 | 171 | ||
| 147 | #ifdef DWARF_SUPPORT | 172 | #ifdef DWARF_SUPPORT |
| @@ -1913,3 +1938,42 @@ int del_perf_probe_events(struct strlist *dellist) | |||
| 1913 | return ret; | 1938 | return ret; |
| 1914 | } | 1939 | } |
| 1915 | 1940 | ||
| 1941 | /* | ||
| 1942 | * If a symbol corresponds to a function with global binding return 0. | ||
| 1943 | * For all others return 1. | ||
| 1944 | */ | ||
| 1945 | static int filter_non_global_functions(struct map *map __unused, | ||
| 1946 | struct symbol *sym) | ||
| 1947 | { | ||
| 1948 | if (sym->binding != STB_GLOBAL) | ||
| 1949 | return 1; | ||
| 1950 | |||
| 1951 | return 0; | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | int show_available_funcs(const char *module) | ||
| 1955 | { | ||
| 1956 | struct map *map; | ||
| 1957 | int ret; | ||
| 1958 | |||
| 1959 | setup_pager(); | ||
| 1960 | |||
| 1961 | ret = init_vmlinux(); | ||
| 1962 | if (ret < 0) | ||
| 1963 | return ret; | ||
| 1964 | |||
| 1965 | map = kernel_get_module_map(module); | ||
| 1966 | if (!map) { | ||
| 1967 | pr_err("Failed to find %s map.\n", (module) ? : "kernel"); | ||
| 1968 | return -EINVAL; | ||
| 1969 | } | ||
| 1970 | if (map__load(map, filter_non_global_functions)) { | ||
| 1971 | pr_err("Failed to load map.\n"); | ||
| 1972 | return -EINVAL; | ||
| 1973 | } | ||
| 1974 | if (!dso__sorted_by_name(map->dso, map->type)) | ||
| 1975 | dso__sort_by_name(map->dso, map->type); | ||
| 1976 | |||
| 1977 | dso__fprintf_symbols_by_name(map->dso, map->type, stdout); | ||
| 1978 | return 0; | ||
| 1979 | } | ||
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 5accbedfea37..1fb4f18337d3 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
| @@ -127,6 +127,7 @@ extern int show_line_range(struct line_range *lr, const char *module); | |||
| 127 | extern int show_available_vars(struct perf_probe_event *pevs, int npevs, | 127 | extern int show_available_vars(struct perf_probe_event *pevs, int npevs, |
| 128 | int max_probe_points, const char *module, | 128 | int max_probe_points, const char *module, |
| 129 | bool externs); | 129 | bool externs); |
| 130 | extern int show_available_funcs(const char *module); | ||
| 130 | 131 | ||
| 131 | 132 | ||
| 132 | /* Maximum index number of event-name postfix */ | 133 | /* Maximum index number of event-name postfix */ |
