Enhances -F/--funcs option of "perf probe" to list possible probe points in an executable file or library. A new option -e/--exe specifies the path of the executable or library. Show last 10 functions in /bin/zsh. # perf probe -F -u -e /bin/zsh | tail zstrtol ztrcmp ztrdup ztrduppfx ztrftime ztrlen ztrncpy ztrsub zwarn zwarnnam Show first 10 functions in /lib/libc.so.6 # perf probe -u -F -e /lib/libc.so.6 | head _IO_adjust_column _IO_adjust_wcolumn _IO_default_doallocate _IO_default_finish _IO_default_pbackfail _IO_default_uflow _IO_default_xsgetn _IO_default_xsputn _IO_do_write@@GLIBC_2.2.5 _IO_doallocbuf Signed-off-by: Srikar Dronamraju <srikar@xxxxxxxxxxxxxxxxxx> --- tools/perf/builtin-probe.c | 9 +++++-- tools/perf/util/probe-event.c | 56 +++++++++++++++++++++++++++++++---------- tools/perf/util/probe-event.h | 4 +-- tools/perf/util/symbol.c | 8 ++++++ tools/perf/util/symbol.h | 1 + 5 files changed, 61 insertions(+), 17 deletions(-) diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 98db08f..6ceebea 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c @@ -57,6 +57,7 @@ static struct { bool show_ext_vars; bool show_funcs; bool mod_events; + bool uprobes; int nevents; struct perf_probe_event events[MAX_PROBES]; struct strlist *dellist; @@ -249,6 +250,10 @@ static const struct option options[] = { "Set how many probe points can be found for a probe."), OPT_BOOLEAN('F', "funcs", ¶ms.show_funcs, "Show potential probe-able functions."), + OPT_BOOLEAN('u', "uprobe", ¶ms.uprobes, + "user space probe events"), + OPT_STRING('e', "exe", ¶ms.target, + "executable", "userspace executable or library"), OPT_CALLBACK('\0', "filter", NULL, "[!]FILTER", "Set a filter (with --vars/funcs only)\n" "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n" @@ -327,8 +332,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) if (!params.filter) params.filter = strfilter__new(DEFAULT_FUNC_FILTER, NULL); - ret = show_available_funcs(params.target, - params.filter); + ret = show_available_funcs(params.target, params.filter, + params.uprobes); strfilter__delete(params.filter); if (ret < 0) pr_err(" Error: Failed to show functions." diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 09c53c1..cf77feb 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -47,6 +47,7 @@ #include "trace-event.h" /* For __unused */ #include "probe-event.h" #include "probe-finder.h" +#include "session.h" #define MAX_CMDLEN 256 #define MAX_PROBE_ARGS 128 @@ -1963,6 +1964,7 @@ int del_perf_probe_events(struct strlist *dellist) return ret; } + /* TODO: don't use a global variable for filter ... */ static struct strfilter *available_func_filter; @@ -1979,30 +1981,58 @@ static int filter_available_functions(struct map *map __unused, return 1; } -int show_available_funcs(const char *elfobject, struct strfilter *_filter) +static int __show_available_funcs(struct map *map) +{ + if (map__load(map, filter_available_functions)) { + pr_err("Failed to load map.\n"); + return -EINVAL; + } + if (!dso__sorted_by_name(map->dso, map->type)) + dso__sort_by_name(map->dso, map->type); + + dso__fprintf_symbols_by_name(map->dso, map->type, stdout); + return 0; +} + +static int available_kernel_funcs(const char *module) { struct map *map; int ret; - setup_pager(); - ret = init_vmlinux(); if (ret < 0) return ret; - map = kernel_get_module_map(elfobject); + map = kernel_get_module_map(module); if (!map) { - pr_err("Failed to find %s map.\n", (elfobject) ? : "kernel"); + pr_err("Failed to find %s map.\n", (module) ? : "kernel"); return -EINVAL; } + return __show_available_funcs(map); +} + +int show_available_funcs(const char *elfobject, struct strfilter *_filter, + bool user) +{ + struct map *map; + int ret; + + setup_pager(); available_func_filter = _filter; - if (map__load(map, filter_available_functions)) { - pr_err("Failed to load map.\n"); - return -EINVAL; - } - if (!dso__sorted_by_name(map->dso, map->type)) - dso__sort_by_name(map->dso, map->type); - dso__fprintf_symbols_by_name(map->dso, map->type, stdout); - return 0; + if (!user) + return available_kernel_funcs(elfobject); + + symbol_conf.try_vmlinux_path = false; + symbol_conf.sort_by_name = true; + ret = symbol__init(); + if (ret < 0) { + pr_err("Failed to init symbol map.\n"); + return ret; + } + map = dso__new_map(elfobject); + ret = __show_available_funcs(map); + dso__delete(map->dso); + map__delete(map); + return ret; } diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 3434fc9..4c24a85 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -128,8 +128,8 @@ extern int show_line_range(struct line_range *lr, const char *module); extern int show_available_vars(struct perf_probe_event *pevs, int npevs, int max_probe_points, const char *module, struct strfilter *filter, bool externs); -extern int show_available_funcs(const char *module, struct strfilter *filter); - +extern int show_available_funcs(const char *module, struct strfilter *filter, + bool user); /* Maximum index number of event-name postfix */ #define MAX_EVENT_INDEX 1024 diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index f06c10f..eefeab4 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -2606,3 +2606,11 @@ int machine__load_vmlinux_path(struct machine *self, enum map_type type, return ret; } + +struct map *dso__new_map(const char *name) +{ + struct dso *dso = dso__new(name); + struct map *map = map__new2(0, dso, MAP__FUNCTION); + + return map; +} diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 713b0b4..3838909 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -211,6 +211,7 @@ char dso__symtab_origin(const struct dso *self); void dso__set_long_name(struct dso *self, char *name); void dso__set_build_id(struct dso *self, void *build_id); void dso__read_running_kernel_build_id(struct dso *self, struct machine *machine); +struct map *dso__new_map(const char *name); struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); struct symbol *dso__find_symbol_by_name(struct dso *self, enum map_type type, const char *name); -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxxx For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>