lkml.org 
[lkml]   [2010]   [Aug]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCHv11a 2.6.36-rc2-tip 12/15] 12: perf: show possible probes in a given file.
    Introduces -S/--show_functions option for perf-probe.
    This lists function names in a File. If no file is specified, then lists
    functions in the current running kernel.

    Signed-off-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
    ---

    Changelog from V11: accomodate name change dso_fprintf_symbols_by_name.

    Changelog from V10: As suggested by Arnaldo, filtering is now
    based on sym.binding.

    Changelog from V9: Filter labels, weak, and local binding functions
    from listing as suggested by Christoph Hellwig.

    Show last 10 functions in /bin/zsh.

    # perf probe -S -D /bin/zsh | tail
    zstrtol
    ztrcmp
    ztrdup
    ztrduppfx
    ztrftime
    ztrlen
    ztrncpy
    ztrsub
    zwarn
    zwarnnam

    Show first 10 functions in /lib/libc.so.6

    # perf probe -S -D /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

    Show last 10 functions in kernel.

    # perf probe -S | tail
    zlib_inflateInit2
    zlib_inflateReset
    zlib_inflate_blob
    zlib_inflate_table
    zlib_inflate_workspacesize
    zone_pcp_update
    zone_reclaim
    zone_reclaimable_pages
    zone_statistics
    zone_watermark_ok
    ---
    tools/perf/builtin-probe.c | 43 ++++++++++++++++++++++++
    tools/perf/util/probe-event.c | 72 +++++++++++++++++++++++++++++++++++++++++
    tools/perf/util/probe-event.h | 1 +
    tools/perf/util/symbol.c | 8 +++++
    tools/perf/util/symbol.h | 1 +
    5 files changed, 124 insertions(+), 1 deletions(-)

    diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
    index 199d5e1..fa63245 100644
    --- a/tools/perf/builtin-probe.c
    +++ b/tools/perf/builtin-probe.c
    @@ -50,9 +50,11 @@ static struct {
    bool list_events;
    bool force_add;
    bool show_lines;
    + bool list_functions;
    int nevents;
    struct perf_probe_event events[MAX_PROBES];
    struct strlist *dellist;
    + struct strlist *limitlist;
    struct line_range line_range;
    int max_probe_points;
    } params;
    @@ -132,6 +134,19 @@ static int opt_show_lines(const struct option *opt __used,
    }
    #endif

    +static int opt_limit_dsos(const struct option *opt __used,
    + const char *str, int unset __used)
    +{
    + if (str) {
    + if (!params.limitlist)
    + params.limitlist = strlist__new(true, NULL);
    + if (!params.limitlist)
    + return -1;
    + strlist__add(params.limitlist, str);
    + }
    + return 0;
    +}
    +
    static const char * const probe_usage[] = {
    "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
    "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
    @@ -188,6 +203,10 @@ static const struct option options[] = {
    OPT__DRY_RUN(&probe_event_dry_run),
    OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
    "Set how many probe points can be found for a probe."),
    + OPT_BOOLEAN('S', "show_functions", &params.list_functions,
    + "Show potential probes."),
    + OPT_CALLBACK('D', "limit_dsos", NULL, "DSO",
    + "Limit Dsos.", opt_limit_dsos),
    OPT_END()
    };

    @@ -213,7 +232,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
    params.max_probe_points = MAX_PROBES;

    if ((!params.nevents && !params.dellist && !params.list_events &&
    - !params.show_lines))
    + !params.show_lines && !params.list_functions))
    usage_with_options(probe_usage, options);

    if (params.list_events) {
    @@ -225,12 +244,34 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
    pr_err(" Error: Don't use --list with --line.\n");
    usage_with_options(probe_usage, options);
    }
    + if (params.list_functions) {
    + pr_warning(" Error: Don't use --list with"
    + " --show_functions.\n");
    + usage_with_options(probe_usage, options);
    + }
    ret = show_perf_probe_events();
    if (ret < 0)
    pr_err(" Error: Failed to show event list. (%d)\n",
    ret);
    return ret;
    }
    + if (params.list_functions) {
    + if (params.nevents != 0 || params.dellist) {
    + pr_err(" Error: Don't use --show_functions with"
    + " --add/--del.\n");
    + usage_with_options(probe_usage, options);
    + }
    + if (params.show_lines) {
    + pr_err(" Error: Don't use --show_functions with"
    + " --line.\n");
    + usage_with_options(probe_usage, options);
    + }
    + ret = show_possible_probes(params.limitlist);
    + if (ret < 0)
    + pr_err(" Error: Failed to show possible"
    + " probes (%d).\n", ret);
    + return ret;
    + }

    #ifdef DWARF_SUPPORT
    if (params.show_lines) {
    diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
    index e72f05c..be90836 100644
    --- a/tools/perf/util/probe-event.c
    +++ b/tools/perf/util/probe-event.c
    @@ -31,6 +31,7 @@
    #include <string.h>
    #include <stdarg.h>
    #include <limits.h>
    +#include <gelf.h>

    #undef _GNU_SOURCE
    #include "util.h"
    @@ -46,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
    @@ -1752,3 +1754,73 @@ int del_perf_probe_events(struct strlist *dellist)
    return ret;
    }

    +/*
    + * If a symbol corresponds to a function with global binding return 0.
    + * For all others return 1.
    + */
    +static int filter_non_global_functions(struct map *map __unused,
    + struct symbol *sym)
    +{
    + if (sym->binding != STB_GLOBAL)
    + return 1;
    +
    + return 0;
    +}
    +
    +static int print_list_available_symbols(struct map *map,
    + const char *name __unused)
    +{
    + if (map__load(map, filter_non_global_functions) < 0)
    + 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;
    +}
    +
    +int show_possible_probes(struct strlist *limitlist)
    +{
    + struct str_node *ent;
    + struct map *map = NULL;
    + char *str;
    + int ret = -EINVAL;
    +
    + if (!limitlist) { /* Show functions in kernel */
    + ret = init_vmlinux();
    + if (ret < 0)
    + return ret;
    + return print_list_available_symbols(
    + machine.vmlinux_maps[MAP__FUNCTION], NULL);
    + }
    +
    + symbol_conf.try_vmlinux_path = false;
    + symbol_conf.sort_by_name = true;
    + ret = symbol__init();
    + if (ret < 0) {
    + pr_debug("Failed to init symbol map.\n");
    + return ret;
    + }
    +
    + strlist__for_each(ent, limitlist) {
    + str = strdup(ent->s);
    + if (!str) {
    + ret = -ENOMEM;
    + goto out_delete;
    + }
    +
    + map = dso__new_map(str);
    + ret = print_list_available_symbols(map, NULL);
    + if (ret)
    + pr_warning("No Symbols in dso %s.\n", str);
    +
    + dso__delete(map->dso);
    + map__delete(map);
    + free(str);
    + }
    +
    +out_delete:
    + if (ret)
    + pr_warning("Failed to list available probes.\n");
    + return ret;
    +}
    diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
    index 5af3924..fcd0f08 100644
    --- a/tools/perf/util/probe-event.h
    +++ b/tools/perf/util/probe-event.h
    @@ -115,6 +115,7 @@ extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
    extern int del_perf_probe_events(struct strlist *dellist);
    extern int show_perf_probe_events(void);
    extern int show_line_range(struct line_range *lr);
    +extern int show_possible_probes(struct strlist *availlist);


    /* Maximum index number of event-name postfix */
    diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
    index a08e1cb..1728d71 100644
    --- a/tools/perf/util/symbol.c
    +++ b/tools/perf/util/symbol.c
    @@ -2464,3 +2464,11 @@ int machine__load_vmlinux_path(struct machine *self, enum map_type type,

    return ret;
    }
    +
    +struct map *dso__new_map(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 0a2c460..145953d 100644
    --- a/tools/perf/util/symbol.h
    +++ b/tools/perf/util/symbol.h
    @@ -202,6 +202,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(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);

    \
     
     \ /
      Last update: 2010-08-27 16:29    [W:0.033 / U:63.372 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site