Subject: [PATCH perf/core v2 0/4] perf-probe code cleanup and support wildcard for probe points

Hi,

Here is a patches for wild card support. I've added two patches to
reduce API parameters by introducing probe_conf. This simplifies
--no-inlines option. (Thanks Arnaldo!)

Changes from v1:
- Update for the latest perf/core
- Use perf_probe_event.target instead of passing it as an independent
parameter [1/4]
- Introduce probe_conf for configuring parameters of probe-finder and
probe-event [2/4]

Thank you,

---

Masami Hiramatsu (4):
perf probe: Use perf_probe_event.target instead of passing as an argument
perf probe: Introduce probe_conf global configs
perf-probe: Add --no-inlines option to avoid searching inline functions
perf-probe: Support glob wildcards for function name


tools/perf/Documentation/perf-probe.txt | 4 +
tools/perf/builtin-probe.c | 24 +++----
tools/perf/util/dwarf-aux.c | 16 +++++
tools/perf/util/dwarf-aux.h | 3 +
tools/perf/util/probe-event.c | 105 +++++++++++++++----------------
tools/perf/util/probe-event.h | 15 +++-
tools/perf/util/probe-finder.c | 44 +++++++++----
tools/perf/util/probe-finder.h | 7 +-
tools/perf/util/util.h | 4 +
9 files changed, 128 insertions(+), 94 deletions(-)


--
Masami HIRAMATSU
Linux Technology Research Center, System Productivity Research Dept.
Center for Technology Innovation - Systems Engineering
Hitachi, Ltd., Research & Development Group
E-mail: [email protected]


Subject: [PATCH perf/core v2 1/4] perf probe: Use perf_probe_event.target instead of passing as an argument

Use perf_probe_event.target field for the target binary
instead of passing it as an argument.

Signed-off-by: Masami Hiramatsu <[email protected]>
---
tools/perf/builtin-probe.c | 1 -
tools/perf/util/probe-event.c | 55 +++++++++++++++++++----------------------
tools/perf/util/probe-event.h | 4 +--
3 files changed, 27 insertions(+), 33 deletions(-)

diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 9c4cf5e..233f941 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -478,7 +478,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)

ret = show_available_vars(params.events, params.nevents,
params.max_probe_points,
- params.target,
params.filter,
params.show_ext_vars);
if (ret < 0)
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 37a3a8b..b8fd48d 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -344,15 +344,14 @@ out:

static int get_alternative_probe_event(struct debuginfo *dinfo,
struct perf_probe_event *pev,
- struct perf_probe_point *tmp,
- const char *target)
+ struct perf_probe_point *tmp)
{
int ret;

memcpy(tmp, &pev->point, sizeof(*tmp));
memset(&pev->point, 0, sizeof(pev->point));
ret = find_alternative_probe_point(dinfo, tmp, &pev->point,
- target, pev->uprobes);
+ pev->target, pev->uprobes);
if (ret < 0)
memcpy(&pev->point, tmp, sizeof(*tmp));

@@ -601,15 +600,14 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
/* Try to find perf_probe_event with debuginfo */
static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event **tevs,
- int max_tevs, const char *target)
+ int max_tevs)
{
bool need_dwarf = perf_probe_event_need_dwarf(pev);
struct perf_probe_point tmp;
struct debuginfo *dinfo;
int ntevs, ret = 0;

- dinfo = open_debuginfo(target, !need_dwarf);
-
+ dinfo = open_debuginfo(pev->target, !need_dwarf);
if (!dinfo) {
if (need_dwarf)
return -ENOENT;
@@ -622,7 +620,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);

if (ntevs == 0) { /* Not found, retry with an alternative */
- ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
+ ret = get_alternative_probe_event(dinfo, pev, &tmp);
if (!ret) {
ntevs = debuginfo__find_trace_events(dinfo, pev,
tevs, max_tevs);
@@ -640,7 +638,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
if (ntevs > 0) { /* Succeeded to find trace events */
pr_debug("Found %d probe_trace_events.\n", ntevs);
ret = post_process_probe_trace_events(*tevs, ntevs,
- target, pev->uprobes);
+ pev->target, pev->uprobes);
if (ret < 0 || ret == ntevs) {
clear_probe_trace_events(*tevs, ntevs);
zfree(tevs);
@@ -824,7 +822,7 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
static int show_available_vars_at(struct debuginfo *dinfo,
struct perf_probe_event *pev,
int max_vls, struct strfilter *_filter,
- bool externs, const char *target)
+ bool externs)
{
char *buf;
int ret, i, nvars;
@@ -841,7 +839,7 @@ static int show_available_vars_at(struct debuginfo *dinfo,
ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
max_vls, externs);
if (!ret) { /* Not found, retry with an alternative */
- ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
+ ret = get_alternative_probe_event(dinfo, pev, &tmp);
if (!ret) {
ret = debuginfo__find_available_vars_at(dinfo, pev,
&vls, max_vls, externs);
@@ -891,8 +889,7 @@ end:

/* Show available variables on given probe point */
int show_available_vars(struct perf_probe_event *pevs, int npevs,
- int max_vls, const char *module,
- struct strfilter *_filter, bool externs)
+ int max_vls, struct strfilter *_filter, bool externs)
{
int i, ret = 0;
struct debuginfo *dinfo;
@@ -901,7 +898,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
if (ret < 0)
return ret;

- dinfo = open_debuginfo(module, false);
+ dinfo = open_debuginfo(pevs->target, false);
if (!dinfo) {
ret = -ENOENT;
goto out;
@@ -911,7 +908,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,

for (i = 0; i < npevs && ret >= 0; i++)
ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
- externs, module);
+ externs);

debuginfo__delete(dinfo);
out:
@@ -931,8 +928,7 @@ find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused,

static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event **tevs __maybe_unused,
- int max_tevs __maybe_unused,
- const char *target __maybe_unused)
+ int max_tevs __maybe_unused)
{
if (perf_probe_event_need_dwarf(pev)) {
pr_warning("Debuginfo-analysis is not supported.\n");
@@ -952,7 +948,6 @@ int show_line_range(struct line_range *lr __maybe_unused,

int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
int npevs __maybe_unused, int max_vls __maybe_unused,
- const char *module __maybe_unused,
struct strfilter *filter __maybe_unused,
bool externs __maybe_unused)
{
@@ -2520,7 +2515,7 @@ void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
*/
static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
struct probe_trace_event **tevs,
- int max_tevs, const char *target)
+ int max_tevs)
{
struct map *map = NULL;
struct ref_reloc_sym *reloc_sym = NULL;
@@ -2531,7 +2526,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
int num_matched_functions;
int ret, i;

- map = get_target_map(target, pev->uprobes);
+ map = get_target_map(pev->target, pev->uprobes);
if (!map) {
ret = -EINVAL;
goto out;
@@ -2544,12 +2539,12 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
num_matched_functions = find_probe_functions(map, pp->function);
if (num_matched_functions == 0) {
pr_err("Failed to find symbol %s in %s\n", pp->function,
- target ? : "kernel");
+ pev->target ? : "kernel");
ret = -ENOENT;
goto out;
} else if (num_matched_functions > max_tevs) {
pr_err("Too many functions matched in %s\n",
- target ? : "kernel");
+ pev->target ? : "kernel");
ret = -E2BIG;
goto out;
}
@@ -2597,8 +2592,9 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
tp->offset = pp->offset;
}
tp->retprobe = pp->retprobe;
- if (target)
- tev->point.module = strdup_or_goto(target, nomem_out);
+ if (pev->target)
+ tev->point.module = strdup_or_goto(pev->target,
+ nomem_out);
tev->uprobes = pev->uprobes;
tev->nargs = pev->nargs;
if (tev->nargs) {
@@ -2639,13 +2635,13 @@ bool __weak arch__prefers_symtab(void) { return false; }

static int convert_to_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event **tevs,
- int max_tevs, const char *target)
+ int max_tevs)
{
int ret;

if (pev->uprobes && !pev->group) {
/* Replace group name if not given */
- ret = convert_exec_to_group(target, &pev->group);
+ ret = convert_exec_to_group(pev->target, &pev->group);
if (ret != 0) {
pr_warning("Failed to make a group name.\n");
return ret;
@@ -2653,17 +2649,17 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
}

if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
- ret = find_probe_trace_events_from_map(pev, tevs, max_tevs, target);
+ ret = find_probe_trace_events_from_map(pev, tevs, max_tevs);
if (ret > 0)
return ret; /* Found in symbol table */
}

/* Convert perf_probe_event with debuginfo */
- ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
+ ret = try_to_find_probe_trace_events(pev, tevs, max_tevs);
if (ret != 0)
return ret; /* Found in debuginfo or got an error */

- return find_probe_trace_events_from_map(pev, tevs, max_tevs, target);
+ return find_probe_trace_events_from_map(pev, tevs, max_tevs);
}

struct __event_package {
@@ -2696,8 +2692,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
/* Convert with or without debuginfo */
ret = convert_to_probe_trace_events(pkgs[i].pev,
&pkgs[i].tevs,
- max_tevs,
- pkgs[i].pev->target);
+ max_tevs);
if (ret < 0)
goto end;
pkgs[i].ntevs = ret;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e10aedc..e3d9bb1 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -131,8 +131,8 @@ extern int show_perf_probe_events(struct strfilter *filter);
extern int show_line_range(struct line_range *lr, const char *module,
bool user);
extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
- int max_probe_points, const char *module,
- struct strfilter *filter, bool externs);
+ int max_probe_points, struct strfilter *filter,
+ bool externs);
extern int show_available_funcs(const char *module, struct strfilter *filter,
bool user);
bool arch__prefers_symtab(void);

Subject: [PATCH perf/core v2 2/4] perf probe: Introduce probe_conf global configs

Introduce probe_conf global configuration parameters for
probe-event and probe-finder, and removes related parameters
from APIs.

Signed-off-by: Masami Hiramatsu <[email protected]>
---
tools/perf/builtin-probe.c | 21 +++++-----------
tools/perf/util/probe-event.c | 53 +++++++++++++++++-----------------------
tools/perf/util/probe-event.h | 13 +++++++---
tools/perf/util/probe-finder.c | 17 ++++++-------
tools/perf/util/probe-finder.h | 7 ++---
5 files changed, 48 insertions(+), 63 deletions(-)

diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 233f941..dbc998f 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -50,8 +50,6 @@
static struct {
int command; /* Command short_name */
bool list_events;
- bool force_add;
- bool show_ext_vars;
bool uprobes;
bool quiet;
bool target_used;
@@ -59,7 +57,6 @@ static struct {
struct perf_probe_event events[MAX_PROBES];
struct line_range line_range;
char *target;
- int max_probe_points;
struct strfilter *filter;
} params;

@@ -364,7 +361,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
"\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
#endif
opt_add_probe_event),
- OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events"
+ OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
" with existing name"),
#ifdef HAVE_DWARF_SUPPORT
OPT_CALLBACK('L', "line", NULL,
@@ -373,7 +370,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_CALLBACK('V', "vars", NULL,
"FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
"Show accessible variables on PROBEDEF", opt_show_vars),
- OPT_BOOLEAN('\0', "externs", &params.show_ext_vars,
+ OPT_BOOLEAN('\0', "externs", &probe_conf.show_ext_vars,
"Show external variables too (with --vars only)"),
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
"file", "vmlinux pathname"),
@@ -384,7 +381,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
opt_set_target),
#endif
OPT__DRY_RUN(&probe_event_dry_run),
- OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
+ OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
"Set how many probe points can be found for a probe."),
OPT_CALLBACK_DEFAULT('F', "funcs", NULL, "[FILTER]",
"Show potential probe-able functions.",
@@ -440,8 +437,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
verbose = -1;
}

- if (params.max_probe_points == 0)
- params.max_probe_points = MAX_PROBES;
+ if (probe_conf.max_probes == 0)
+ probe_conf.max_probes = MAX_PROBES;

/*
* Only consider the user's kernel image path if given.
@@ -477,9 +474,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
NULL);

ret = show_available_vars(params.events, params.nevents,
- params.max_probe_points,
- params.filter,
- params.show_ext_vars);
+ params.filter);
if (ret < 0)
pr_err_with_code(" Error: Failed to show vars.", ret);
return ret;
@@ -498,9 +493,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
usage_with_options(probe_usage, options);
}

- ret = add_perf_probe_events(params.events, params.nevents,
- params.max_probe_points,
- params.force_add);
+ ret = add_perf_probe_events(params.events, params.nevents);
if (ret < 0) {
pr_err_with_code(" Error: Failed to add events.", ret);
return ret;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index b8fd48d..a7deda4 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -51,6 +51,7 @@
#define PERFPROBE_GROUP "probe"

bool probe_event_dry_run; /* Dry run flag */
+struct probe_conf probe_conf;

#define semantic_error(msg ...) pr_err("Semantic error :" msg)

@@ -599,8 +600,7 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,

/* Try to find perf_probe_event with debuginfo */
static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
- struct probe_trace_event **tevs,
- int max_tevs)
+ struct probe_trace_event **tevs)
{
bool need_dwarf = perf_probe_event_need_dwarf(pev);
struct perf_probe_point tmp;
@@ -617,13 +617,12 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,

pr_debug("Try to find probe point from debuginfo.\n");
/* Searching trace events corresponding to a probe event */
- ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
+ ntevs = debuginfo__find_trace_events(dinfo, pev, tevs);

if (ntevs == 0) { /* Not found, retry with an alternative */
ret = get_alternative_probe_event(dinfo, pev, &tmp);
if (!ret) {
- ntevs = debuginfo__find_trace_events(dinfo, pev,
- tevs, max_tevs);
+ ntevs = debuginfo__find_trace_events(dinfo, pev, tevs);
/*
* Write back to the original probe_event for
* setting appropriate (user given) event name
@@ -821,8 +820,7 @@ int show_line_range(struct line_range *lr, const char *module, bool user)

static int show_available_vars_at(struct debuginfo *dinfo,
struct perf_probe_event *pev,
- int max_vls, struct strfilter *_filter,
- bool externs)
+ struct strfilter *_filter)
{
char *buf;
int ret, i, nvars;
@@ -836,13 +834,12 @@ static int show_available_vars_at(struct debuginfo *dinfo,
return -EINVAL;
pr_debug("Searching variables at %s\n", buf);

- ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
- max_vls, externs);
+ ret = debuginfo__find_available_vars_at(dinfo, pev, &vls);
if (!ret) { /* Not found, retry with an alternative */
ret = get_alternative_probe_event(dinfo, pev, &tmp);
if (!ret) {
ret = debuginfo__find_available_vars_at(dinfo, pev,
- &vls, max_vls, externs);
+ &vls);
/* Release the old probe_point */
clear_perf_probe_point(&tmp);
}
@@ -889,7 +886,7 @@ end:

/* Show available variables on given probe point */
int show_available_vars(struct perf_probe_event *pevs, int npevs,
- int max_vls, struct strfilter *_filter, bool externs)
+ struct strfilter *_filter)
{
int i, ret = 0;
struct debuginfo *dinfo;
@@ -907,8 +904,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
setup_pager();

for (i = 0; i < npevs && ret >= 0; i++)
- ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
- externs);
+ ret = show_available_vars_at(dinfo, &pevs[i], _filter);

debuginfo__delete(dinfo);
out:
@@ -927,8 +923,7 @@ find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused,
}

static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
- struct probe_trace_event **tevs __maybe_unused,
- int max_tevs __maybe_unused)
+ struct probe_trace_event **tevs __maybe_unused)
{
if (perf_probe_event_need_dwarf(pev)) {
pr_warning("Debuginfo-analysis is not supported.\n");
@@ -947,9 +942,8 @@ int show_line_range(struct line_range *lr __maybe_unused,
}

int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
- int npevs __maybe_unused, int max_vls __maybe_unused,
- struct strfilter *filter __maybe_unused,
- bool externs __maybe_unused)
+ int npevs __maybe_unused,
+ struct strfilter *filter __maybe_unused)
{
pr_warning("Debuginfo-analysis is not supported.\n");
return -ENOSYS;
@@ -2514,8 +2508,7 @@ void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
* Return an error or the number of found probe_trace_event
*/
static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
- struct probe_trace_event **tevs,
- int max_tevs)
+ struct probe_trace_event **tevs)
{
struct map *map = NULL;
struct ref_reloc_sym *reloc_sym = NULL;
@@ -2542,7 +2535,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
pev->target ? : "kernel");
ret = -ENOENT;
goto out;
- } else if (num_matched_functions > max_tevs) {
+ } else if (num_matched_functions > probe_conf.max_probes) {
pr_err("Too many functions matched in %s\n",
pev->target ? : "kernel");
ret = -E2BIG;
@@ -2634,8 +2627,7 @@ err_out:
bool __weak arch__prefers_symtab(void) { return false; }

static int convert_to_probe_trace_events(struct perf_probe_event *pev,
- struct probe_trace_event **tevs,
- int max_tevs)
+ struct probe_trace_event **tevs)
{
int ret;

@@ -2649,17 +2641,17 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
}

if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
- ret = find_probe_trace_events_from_map(pev, tevs, max_tevs);
+ ret = find_probe_trace_events_from_map(pev, tevs);
if (ret > 0)
return ret; /* Found in symbol table */
}

/* Convert perf_probe_event with debuginfo */
- ret = try_to_find_probe_trace_events(pev, tevs, max_tevs);
+ ret = try_to_find_probe_trace_events(pev, tevs);
if (ret != 0)
return ret; /* Found in debuginfo or got an error */

- return find_probe_trace_events_from_map(pev, tevs, max_tevs);
+ return find_probe_trace_events_from_map(pev, tevs);
}

struct __event_package {
@@ -2668,8 +2660,7 @@ struct __event_package {
int ntevs;
};

-int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
- int max_tevs, bool force_add)
+int add_perf_probe_events(struct perf_probe_event *pevs, int npevs)
{
int i, j, ret;
struct __event_package *pkgs;
@@ -2691,8 +2682,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
pkgs[i].pev = &pevs[i];
/* Convert with or without debuginfo */
ret = convert_to_probe_trace_events(pkgs[i].pev,
- &pkgs[i].tevs,
- max_tevs);
+ &pkgs[i].tevs);
if (ret < 0)
goto end;
pkgs[i].ntevs = ret;
@@ -2701,7 +2691,8 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
/* Loop 2: add all events */
for (i = 0; i < npevs; i++) {
ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
- pkgs[i].ntevs, force_add);
+ pkgs[i].ntevs,
+ probe_conf.force_add);
if (ret < 0)
break;
}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e3d9bb1..db9a9cb2 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -6,6 +6,13 @@
#include "strlist.h"
#include "strfilter.h"

+/* Probe related configurations */
+struct probe_conf {
+ bool show_ext_vars;
+ bool force_add;
+ int max_probes;
+};
+extern struct probe_conf probe_conf;
extern bool probe_event_dry_run;

/* kprobe-tracer and uprobe-tracer tracing point */
@@ -124,15 +131,13 @@ extern int line_range__init(struct line_range *lr);
/* Internal use: Return kernel/module path */
extern const char *kernel_get_module_path(const char *module);

-extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
- int max_probe_points, bool force_add);
+extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
extern int del_perf_probe_events(struct strfilter *filter);
extern int show_perf_probe_events(struct strfilter *filter);
extern int show_line_range(struct line_range *lr, const char *module,
bool user);
extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
- int max_probe_points, struct strfilter *filter,
- bool externs);
+ struct strfilter *filter);
extern int show_available_funcs(const char *module, struct strfilter *filter,
bool user);
bool arch__prefers_symtab(void);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 63d3389..f4f5eed 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1214,15 +1214,15 @@ end:
/* Find probe_trace_events specified by perf_probe_event from debuginfo */
int debuginfo__find_trace_events(struct debuginfo *dbg,
struct perf_probe_event *pev,
- struct probe_trace_event **tevs, int max_tevs)
+ struct probe_trace_event **tevs)
{
struct trace_event_finder tf = {
.pf = {.pev = pev, .callback = add_probe_trace_event},
- .mod = dbg->mod, .max_tevs = max_tevs};
+ .max_tevs = probe_conf.max_probes, .mod = dbg->mod};
int ret;

/* Allocate result tevs array */
- *tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs);
+ *tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs);
if (*tevs == NULL)
return -ENOMEM;

@@ -1303,9 +1303,9 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);

/* Find external variables */
- if (!af->externs)
+ if (!probe_conf.show_ext_vars)
goto out;
- /* Don't need to search child DIE for externs. */
+ /* Don't need to search child DIE for external vars. */
af->child = false;
die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);

@@ -1325,17 +1325,16 @@ out:
*/
int debuginfo__find_available_vars_at(struct debuginfo *dbg,
struct perf_probe_event *pev,
- struct variable_list **vls,
- int max_vls, bool externs)
+ struct variable_list **vls)
{
struct available_var_finder af = {
.pf = {.pev = pev, .callback = add_available_vars},
.mod = dbg->mod,
- .max_vls = max_vls, .externs = externs};
+ .max_vls = probe_conf.max_probes};
int ret;

/* Allocate result vls array */
- *vls = zalloc(sizeof(struct variable_list) * max_vls);
+ *vls = zalloc(sizeof(struct variable_list) * af.max_vls);
if (*vls == NULL)
return -ENOMEM;

diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index f53553d..bed8271 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -40,8 +40,7 @@ extern void debuginfo__delete(struct debuginfo *dbg);
/* Find probe_trace_events specified by perf_probe_event from debuginfo */
extern int debuginfo__find_trace_events(struct debuginfo *dbg,
struct perf_probe_event *pev,
- struct probe_trace_event **tevs,
- int max_tevs);
+ struct probe_trace_event **tevs);

/* Find a perf_probe_point from debuginfo */
extern int debuginfo__find_probe_point(struct debuginfo *dbg,
@@ -55,8 +54,7 @@ extern int debuginfo__find_line_range(struct debuginfo *dbg,
/* Find available variables */
extern int debuginfo__find_available_vars_at(struct debuginfo *dbg,
struct perf_probe_event *pev,
- struct variable_list **vls,
- int max_points, bool externs);
+ struct variable_list **vls);

/* Find a src file from a DWARF tag path */
int get_real_path(const char *raw_path, const char *comp_dir,
@@ -99,7 +97,6 @@ struct available_var_finder {
struct variable_list *vls; /* Found variable lists */
int nvls; /* Number of variable lists */
int max_vls; /* Max no. of variable lists */
- bool externs; /* Find external vars too */
bool child; /* Search child scopes */
};

Subject: [PATCH perf/core v2 3/4] perf-probe: Add --no-inlines option to avoid searching inline functions

Add --no-inlines(--inlines) option to avoid searching inline
functions.
Searching all functions which matches glob pattern can take a
long time and find a lot of inline functions. With this option
perf-probe searches target on the non-inlined functions.

Signed-off-by: Masami Hiramatsu <[email protected]>
---
tools/perf/Documentation/perf-probe.txt | 4 ++++
tools/perf/builtin-probe.c | 2 ++
tools/perf/util/probe-event.h | 1 +
tools/perf/util/probe-finder.c | 2 +-
4 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index ad3e355..3a8a9ba 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -83,6 +83,10 @@ OPTIONS
(Only for --vars) Show external defined variables in addition to local
variables.

+--no-inlines::
+ (Only for --add) Search only for non-inlined functions. The functions
+ which do not have instances are ignored.
+
-F::
--funcs[=FILTER]::
Show available functions in given module or kernel. With -x/--exec,
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index dbc998f..7fa2c7a 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -379,6 +379,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_CALLBACK('m', "module", NULL, "modname|path",
"target module name (for online) or path (for offline)",
opt_set_target),
+ OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
+ "Don't search inlined functions"),
#endif
OPT__DRY_RUN(&probe_event_dry_run),
OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index db9a9cb2..633aba7 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -10,6 +10,7 @@
struct probe_conf {
bool show_ext_vars;
bool force_add;
+ bool no_inlines;
int max_probes;
};
extern struct probe_conf probe_conf;
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index f4f5eed..1713421 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -943,7 +943,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
/* TODO: Check the address in this function */
param->retval = call_probe_finder(sp_die, pf);
}
- } else
+ } else if (!probe_conf.no_inlines)
/* Inlined function: search instances */
param->retval = die_walk_instances(sp_die,
probe_point_inline_cb, (void *)pf);

Subject: [PATCH perf/core v2 4/4] perf-probe: Support glob wildcards for function name

Support glob wildcards for function name when adding
new probes. This will allow us to build caches of
function-entry level information with $params.

e.g.
----
# perf probe --no-inlines --add 'kmalloc* $params'
Added new events:
probe:kmalloc_slab (on kmalloc* with $params)
probe:kmalloc_large_node (on kmalloc* with $params)
probe:kmalloc_order_trace (on kmalloc* with $params)

You can now use it in all perf tools, such as:

perf record -e probe:kmalloc_order_trace -aR sleep 1

# perf probe --list
probe:kmalloc_large_node (on kmalloc_large_node@mm/slub.c with size flags node)
probe:kmalloc_order_trace (on kmalloc_order_trace@mm/slub.c with size flags order)
probe:kmalloc_slab (on kmalloc_slab@mm/slab_common.c with size flags)
----

Signed-off-by: Masami Hiramatsu <[email protected]>
---
tools/perf/util/dwarf-aux.c | 16 ++++++++++++++++
tools/perf/util/dwarf-aux.h | 3 +++
tools/perf/util/probe-event.c | 19 ++++++++++++++-----
tools/perf/util/probe-event.h | 1 +
tools/perf/util/probe-finder.c | 27 +++++++++++++++++++++------
tools/perf/util/util.h | 4 ++++
6 files changed, 59 insertions(+), 11 deletions(-)

diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index c34e024..16d46e2 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -139,11 +139,27 @@ int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
{
const char *name;
+
name = dwarf_diename(dw_die);
return name ? (strcmp(tname, name) == 0) : false;
}

/**
+ * die_match_name - Match diename and glob
+ * @dw_die: a DIE
+ * @glob: a string of target glob pattern
+ *
+ * Glob matching the name of @dw_die and @glob. Return false if matching fail.
+ */
+bool die_match_name(Dwarf_Die *dw_die, const char *glob)
+{
+ const char *name;
+
+ name = dwarf_diename(dw_die);
+ return name ? strglobmatch(name, glob) : false;
+}
+
+/**
* die_get_call_lineno - Get callsite line number of inline-function instance
* @in_die: a DIE of an inlined function instance
*
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index af7dbcd..50a3cdc 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -47,6 +47,9 @@ extern bool die_is_func_instance(Dwarf_Die *dw_die);
/* Compare diename and tname */
extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);

+/* Matching diename with glob pattern */
+extern bool die_match_name(Dwarf_Die *dw_die, const char *glob);
+
/* Get callsite line number of inline-function instance */
extern int die_get_call_lineno(Dwarf_Die *in_die);

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index a7deda4..a2d8cef 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -589,7 +589,11 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
if (!tmp)
return -ENOMEM;
}
- free(tevs[i].point.symbol);
+ /* If we have no realname, use symbol for it */
+ if (!tevs[i].point.realname)
+ tevs[i].point.realname = tevs[i].point.symbol;
+ else
+ free(tevs[i].point.symbol);
tevs[i].point.symbol = tmp;
tevs[i].point.offset = tevs[i].point.address -
reloc_sym->unrelocated_addr;
@@ -1900,6 +1904,7 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
free(tev->event);
free(tev->group);
free(tev->point.symbol);
+ free(tev->point.realname);
free(tev->point.module);
for (i = 0; i < tev->nargs; i++) {
free(tev->args[i].name);
@@ -2377,6 +2382,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
struct strlist *namelist;
LIST_HEAD(blacklist);
struct kprobe_blacklist_node *node;
+ bool safename;

if (pev->uprobes)
fd = open_uprobe_events(true);
@@ -2402,6 +2408,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
pr_debug("No kprobe blacklist support, ignored\n");
}

+ safename = (pev->point.function && !strisglob(pev->point.function));
ret = 0;
pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
for (i = 0; i < ntevs; i++) {
@@ -2420,10 +2427,10 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
if (pev->event)
event = pev->event;
else
- if (pev->point.function)
+ if (safename)
event = pev->point.function;
else
- event = tev->point.symbol;
+ event = tev->point.realname;
if (pev->group)
group = pev->group;
else
@@ -2488,9 +2495,11 @@ static int find_probe_functions(struct map *map, char *name)
{
int found = 0;
struct symbol *sym;
+ struct rb_node *tmp;

- map__for_each_symbol_by_name(map, name, sym) {
- found++;
+ map__for_each_symbol(map, sym, tmp) {
+ if (strglobmatch(sym->name, name))
+ found++;
}

return found;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 633aba7..1e2faa3 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -18,6 +18,7 @@ extern bool probe_event_dry_run;

/* kprobe-tracer and uprobe-tracer tracing point */
struct probe_trace_point {
+ char *realname; /* function real name (if needed) */
char *symbol; /* Base symbol */
char *module; /* Module name */
unsigned long offset; /* Offset from symbol */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 1713421..d5f60c0 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -717,7 +717,7 @@ static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
}
/* If the function name is given, that's what user expects */
if (fsp->function) {
- if (die_compare_name(fn_die, fsp->function)) {
+ if (die_match_name(fn_die, fsp->function)) {
memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
fsp->found = true;
return 1;
@@ -920,13 +920,14 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)

/* Check tag and diename */
if (!die_is_func_def(sp_die) ||
- !die_compare_name(sp_die, pp->function))
+ !die_match_name(sp_die, pp->function))
return DWARF_CB_OK;

/* Check declared file */
if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
return DWARF_CB_OK;

+ pr_debug("Matched function: %s\n", dwarf_diename(sp_die));
pf->fname = dwarf_decl_file(sp_die);
if (pp->line) { /* Function relative line */
dwarf_decl_line(sp_die, &pf->lno);
@@ -943,10 +944,20 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
/* TODO: Check the address in this function */
param->retval = call_probe_finder(sp_die, pf);
}
- } else if (!probe_conf.no_inlines)
+ } else if (!probe_conf.no_inlines) {
/* Inlined function: search instances */
param->retval = die_walk_instances(sp_die,
probe_point_inline_cb, (void *)pf);
+ /* This could be a non-existed inline definition */
+ if (param->retval == -ENOENT && strisglob(pp->function))
+ param->retval = 0;
+ }
+
+ /* We need to find other candidates */
+ if (strisglob(pp->function) && param->retval >= 0) {
+ param->retval = 0; /* We have to clear the result */
+ return DWARF_CB_OK;
+ }

return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
}
@@ -975,7 +986,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
return DWARF_CB_OK;

- if (die_compare_name(param->sp_die, param->function)) {
+ if (die_match_name(param->sp_die, param->function)) {
if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
return DWARF_CB_OK;

@@ -1028,7 +1039,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
return -ENOMEM;

/* Fastpath: lookup by function name from .debug_pubnames section */
- if (pp->function) {
+ if (pp->function && !strisglob(pp->function)) {
struct pubname_callback_param pubname_param = {
.function = pp->function,
.file = pp->file,
@@ -1177,6 +1188,10 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
if (ret < 0)
return ret;

+ tev->point.realname = strdup(dwarf_diename(sc_die));
+ if (!tev->point.realname)
+ return -ENOMEM;
+
pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
tev->point.offset);

@@ -1535,7 +1550,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
return DWARF_CB_OK;

if (die_is_func_def(sp_die) &&
- die_compare_name(sp_die, lr->function)) {
+ die_match_name(sp_die, lr->function)) {
lf->fname = dwarf_decl_file(sp_die);
dwarf_decl_line(sp_die, &lr->offset);
pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 1ff23e0..3601ffd 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -257,6 +257,10 @@ char **argv_split(const char *str, int *argcp);
void argv_free(char **argv);
bool strglobmatch(const char *str, const char *pat);
bool strlazymatch(const char *str, const char *pat);
+static inline bool strisglob(const char *str)
+{
+ return strpbrk(str, "*?[") != NULL;
+}
int strtailcmp(const char *s1, const char *s2);
char *strxfrchar(char *s, char from, char to);
unsigned long convert_unit(unsigned long value, char *unit);

2015-05-08 19:38:47

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH perf/core v2 0/4] perf-probe code cleanup and support wildcard for probe points

Em Fri, May 08, 2015 at 10:03:26AM +0900, Masami Hiramatsu escreveu:
> Hi,
>
> Here is a patches for wild card support. I've added two patches to
> reduce API parameters by introducing probe_conf. This simplifies
> --no-inlines option. (Thanks Arnaldo!)
>
> Changes from v1:
> - Update for the latest perf/core
> - Use perf_probe_event.target instead of passing it as an independent
> parameter [1/4]
> - Introduce probe_conf for configuring parameters of probe-finder and
> probe-event [2/4]
>
> Thank you,
>
> ---
>
> Masami Hiramatsu (4):
> perf probe: Use perf_probe_event.target instead of passing as an argument
> perf probe: Introduce probe_conf global configs
> perf-probe: Add --no-inlines option to avoid searching inline functions
> perf-probe: Support glob wildcards for function name

Excellent stuff! Thanks, all tested.

And here is the example I used to test it plus other goodies:

System wide syscall tracing + kmalloc* kernel functions with its parameters,
filtering the pid of the sshd session to the test machine, to avoid a feedback
loop:

[root@ssdandy ~]# perf probe --no-inlines --add 'kmalloc* $params'
Added new events:
probe:kmalloc_order (on kmalloc* with $params)
probe:kmalloc_order_trace (on kmalloc* with $params)
probe:kmalloc_slab (on kmalloc* with $params)
probe:kmalloc_large_node (on kmalloc* with $params)

You can now use it in all perf tools, such as:

perf record -e probe:kmalloc_large_node -aR sleep 1

[root@ssdandy ~]# perf trace --ev probe:kmalloc* --filter-pids 27206
0.000 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
0.010 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
0.343 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x98 flags=0x10)
73.254 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
73.259 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
89.510 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
192.295 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
205.520 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
205.524 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
260.034 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
260.039 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x300 flags=0x10220)
307.779 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
307.784 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
362.450 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
362.455 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x300 flags=0x10220)
380.507 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
380.511 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
409.663 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
409.668 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
464.868 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
464.874 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x300 flags=0x10220)
499.303 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
512.083 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
512.088 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
585.349 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
585.354 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
614.513 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
614.518 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
669.706 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
669.710 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x300 flags=0x10220)
716.927 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
716.932 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
790.181 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
790.185 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
818.857 ( 0.000 ms): tuned/837 ... [continued]: select()) = 0 Timeout
819.568 ( 0.651 ms): tuned/837 select(tvp: 0x7fb3bb1f9e50 ) ...
819.568 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
819.573 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
879.453 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
879.458 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x300 flags=0x10220)
922.236 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
924.408 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
924.412 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1024.172 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1024.177 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1079.381 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1079.386 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x300 flags=0x10220)
1097.435 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1097.439 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1115.571 ( 0.000 ms): avahi-daemon/745 ... [continued]: poll()) = 0 Timeout
1115.592 ( 0.006 ms): avahi-daemon/745 write(fd: 7<pipe:[10912]>, buf: 0x7ffc066e35bf, count: 1) = 1
1115.596 ( 0.002 ms): avahi-daemon/745 write(fd: 7<pipe:[10912]>, buf: 0x7ffc066e35bf, count: 1) = 1
1115.602 ( 0.003 ms): avahi-daemon/745 read(fd: 6<pipe:[10912]>, buf: 0x7ffc066e35e0, count: 10) = 2
1115.607 ( 0.003 ms): avahi-daemon/745 poll(ufds: 0xaffa40, nfds: 8 ) = 0 Timeout
1115.612 ( 0.002 ms): avahi-daemon/745 write(fd: 7<pipe:[10912]>, buf: 0x7ffc066e35bf, count: 1) = 1
1115.616 ( 0.002 ms): avahi-daemon/745 write(fd: 7<pipe:[10912]>, buf: 0x7ffc066e35bf, count: 1) = 1
1115.620 ( 0.002 ms): avahi-daemon/745 read(fd: 6<pipe:[10912]>, buf: 0x7ffc066e35e0, count: 10) = 2
1126.606 (10.985 ms): avahi-daemon/745 poll(ufds: 0xaffa40, nfds: 8, timeout_msecs: 647 ) ...
1126.606 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1126.612 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1199.853 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1199.858 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1216.042 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1229.103 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1229.107 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1302.275 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1302.279 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1318.900 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1331.434 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1331.438 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1360.755 ( 0.000 ms): lsmd/746 ... [continued]: select()) = 0 Timeout
1360.764 ( 0.003 ms): lsmd/746 waitid(infop: 0x7ffeee2cdc90, options: 5 ) = -10
1404.691 (43.920 ms): lsmd/746 select(n: 6, inp: 0x7ffeee2cdd50, tvp: 0x7ffeee2cdd40 ) ...
1404.691 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1404.696 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1434.623 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1434.628 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1523.298 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1536.268 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1536.273 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1609.524 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1609.528 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1638.684 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1638.688 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1711.943 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1711.948 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1741.098 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1741.102 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1763.390 (647.769 ms): avahi-daemon/745 ... [continued]: poll()) = 0 Timeout
1763.401 ( 0.003 ms): avahi-daemon/745 write(fd: 7<pipe:[10912]>, buf: 0x7ffc066e35bf, count: 1) = 1
1763.404 ( 0.002 ms): avahi-daemon/745 write(fd: 7<pipe:[10912]>, buf: 0x7ffc066e35bf, count: 1) = 1
1763.408 ( 0.002 ms): avahi-daemon/745 read(fd: 6<pipe:[10912]>, buf: 0x7ffc066e35e0, count: 10) = 2
1814.362 (50.952 ms): avahi-daemon/745 poll(ufds: 0xaffa40, nfds: 8, timeout_msecs: 204419 ) ...
1814.362 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1814.367 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1820.100 (1001.183 ms): tuned/837 ... [continued]: select()) = 0 Timeout
1843.529 (23.407 ms): tuned/837 select(tvp: 0x7fb3bb1f9e50 ) ...
1843.529 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
1843.533 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
1945.941 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
^C
[root@ssdandy ~]# perf probe -d '*'
Removed event: probe:kmalloc_large_node
Removed event: probe:kmalloc_order
Removed event: probe:kmalloc_order_trace
Removed event: probe:kmalloc_slab
[root@ssdandy ~]#


:-)

- Arnaldo

Subject: Re: Re: [PATCH perf/core v2 0/4] perf-probe code cleanup and support wildcard for probe points

On 2015/05/09 4:38, Arnaldo Carvalho de Melo wrote:
> Em Fri, May 08, 2015 at 10:03:26AM +0900, Masami Hiramatsu escreveu:
>> Hi,
>>
>> Here is a patches for wild card support. I've added two patches to
>> reduce API parameters by introducing probe_conf. This simplifies
>> --no-inlines option. (Thanks Arnaldo!)
>>
>> Changes from v1:
>> - Update for the latest perf/core
>> - Use perf_probe_event.target instead of passing it as an independent
>> parameter [1/4]
>> - Introduce probe_conf for configuring parameters of probe-finder and
>> probe-event [2/4]
>>
>> Thank you,
>>
>> ---
>>
>> Masami Hiramatsu (4):
>> perf probe: Use perf_probe_event.target instead of passing as an argument
>> perf probe: Introduce probe_conf global configs
>> perf-probe: Add --no-inlines option to avoid searching inline functions
>> perf-probe: Support glob wildcards for function name
>
> Excellent stuff! Thanks, all tested.

Thank you for this good example! :)
Using this with perf-trace is certainly nice usage.

Thank you!

>
> And here is the example I used to test it plus other goodies:
>
> System wide syscall tracing + kmalloc* kernel functions with its parameters,
> filtering the pid of the sshd session to the test machine, to avoid a feedback
> loop:
>
> [root@ssdandy ~]# perf probe --no-inlines --add 'kmalloc* $params'
> Added new events:
> probe:kmalloc_order (on kmalloc* with $params)
> probe:kmalloc_order_trace (on kmalloc* with $params)
> probe:kmalloc_slab (on kmalloc* with $params)
> probe:kmalloc_large_node (on kmalloc* with $params)
>
> You can now use it in all perf tools, such as:
>
> perf record -e probe:kmalloc_large_node -aR sleep 1
>
> [root@ssdandy ~]# perf trace --ev probe:kmalloc* --filter-pids 27206
> 0.000 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 0.010 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 0.343 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x98 flags=0x10)
> 73.254 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 73.259 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 89.510 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 192.295 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 205.520 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 205.524 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 260.034 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 260.039 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x300 flags=0x10220)
> 307.779 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 307.784 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 362.450 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 362.455 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x300 flags=0x10220)
> 380.507 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 380.511 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 409.663 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 409.668 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 464.868 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 464.874 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x300 flags=0x10220)
> 499.303 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 512.083 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 512.088 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 585.349 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 585.354 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 614.513 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 614.518 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 669.706 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 669.710 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x300 flags=0x10220)
> 716.927 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 716.932 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 790.181 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 790.185 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 818.857 ( 0.000 ms): tuned/837 ... [continued]: select()) = 0 Timeout
> 819.568 ( 0.651 ms): tuned/837 select(tvp: 0x7fb3bb1f9e50 ) ...
> 819.568 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 819.573 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 879.453 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 879.458 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x300 flags=0x10220)
> 922.236 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 924.408 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 924.412 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1024.172 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1024.177 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1079.381 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1079.386 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x300 flags=0x10220)
> 1097.435 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1097.439 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1115.571 ( 0.000 ms): avahi-daemon/745 ... [continued]: poll()) = 0 Timeout
> 1115.592 ( 0.006 ms): avahi-daemon/745 write(fd: 7<pipe:[10912]>, buf: 0x7ffc066e35bf, count: 1) = 1
> 1115.596 ( 0.002 ms): avahi-daemon/745 write(fd: 7<pipe:[10912]>, buf: 0x7ffc066e35bf, count: 1) = 1
> 1115.602 ( 0.003 ms): avahi-daemon/745 read(fd: 6<pipe:[10912]>, buf: 0x7ffc066e35e0, count: 10) = 2
> 1115.607 ( 0.003 ms): avahi-daemon/745 poll(ufds: 0xaffa40, nfds: 8 ) = 0 Timeout
> 1115.612 ( 0.002 ms): avahi-daemon/745 write(fd: 7<pipe:[10912]>, buf: 0x7ffc066e35bf, count: 1) = 1
> 1115.616 ( 0.002 ms): avahi-daemon/745 write(fd: 7<pipe:[10912]>, buf: 0x7ffc066e35bf, count: 1) = 1
> 1115.620 ( 0.002 ms): avahi-daemon/745 read(fd: 6<pipe:[10912]>, buf: 0x7ffc066e35e0, count: 10) = 2
> 1126.606 (10.985 ms): avahi-daemon/745 poll(ufds: 0xaffa40, nfds: 8, timeout_msecs: 647 ) ...
> 1126.606 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1126.612 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1199.853 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1199.858 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1216.042 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1229.103 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1229.107 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1302.275 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1302.279 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1318.900 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1331.434 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1331.438 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1360.755 ( 0.000 ms): lsmd/746 ... [continued]: select()) = 0 Timeout
> 1360.764 ( 0.003 ms): lsmd/746 waitid(infop: 0x7ffeee2cdc90, options: 5 ) = -10
> 1404.691 (43.920 ms): lsmd/746 select(n: 6, inp: 0x7ffeee2cdd50, tvp: 0x7ffeee2cdd40 ) ...
> 1404.691 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1404.696 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1434.623 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1434.628 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1523.298 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1536.268 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1536.273 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1609.524 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1609.528 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1638.684 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1638.688 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1711.943 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1711.948 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1741.098 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1741.102 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1763.390 (647.769 ms): avahi-daemon/745 ... [continued]: poll()) = 0 Timeout
> 1763.401 ( 0.003 ms): avahi-daemon/745 write(fd: 7<pipe:[10912]>, buf: 0x7ffc066e35bf, count: 1) = 1
> 1763.404 ( 0.002 ms): avahi-daemon/745 write(fd: 7<pipe:[10912]>, buf: 0x7ffc066e35bf, count: 1) = 1
> 1763.408 ( 0.002 ms): avahi-daemon/745 read(fd: 6<pipe:[10912]>, buf: 0x7ffc066e35e0, count: 10) = 2
> 1814.362 (50.952 ms): avahi-daemon/745 poll(ufds: 0xaffa40, nfds: 8, timeout_msecs: 204419 ) ...
> 1814.362 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1814.367 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1820.100 (1001.183 ms): tuned/837 ... [continued]: select()) = 0 Timeout
> 1843.529 (23.407 ms): tuned/837 select(tvp: 0x7fb3bb1f9e50 ) ...
> 1843.529 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> 1843.533 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x2c0 flags=0x10220)
> 1945.941 ( ): probe:kmalloc_slab:(ffffffff81198ab0) size=0x1c0 flags=0x10220)
> ^C
> [root@ssdandy ~]# perf probe -d '*'
> Removed event: probe:kmalloc_large_node
> Removed event: probe:kmalloc_order
> Removed event: probe:kmalloc_order_trace
> Removed event: probe:kmalloc_slab
> [root@ssdandy ~]#
>
>
> :-)
>
> - Arnaldo
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>


--
Masami HIRAMATSU
Linux Technology Research Center, System Productivity Research Dept.
Center for Technology Innovation - Systems Engineering
Hitachi, Ltd., Research & Development Group
E-mail: [email protected]

Subject: [tip:perf/core] perf probe: Use perf_probe_event.target instead of passing as an argument

Commit-ID: 442255215cb9651668cb09350b0d51e111219f17
Gitweb: http://git.kernel.org/tip/442255215cb9651668cb09350b0d51e111219f17
Author: Masami Hiramatsu <[email protected]>
AuthorDate: Fri, 8 May 2015 10:03:28 +0900
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Fri, 8 May 2015 16:25:21 -0300

perf probe: Use perf_probe_event.target instead of passing as an argument

Use perf_probe_event.target field for the target binary instead of
passing it as an argument.

Signed-off-by: Masami Hiramatsu <[email protected]>
Cc: Ananth N Mavinakayanahalli <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Hemant Kumar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-probe.c | 1 -
tools/perf/util/probe-event.c | 55 ++++++++++++++++++++-----------------------
tools/perf/util/probe-event.h | 4 ++--
3 files changed, 27 insertions(+), 33 deletions(-)

diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 9c4cf5e..233f941 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -478,7 +478,6 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)

ret = show_available_vars(params.events, params.nevents,
params.max_probe_points,
- params.target,
params.filter,
params.show_ext_vars);
if (ret < 0)
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 37a3a8b..b8fd48d 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -344,15 +344,14 @@ out:

static int get_alternative_probe_event(struct debuginfo *dinfo,
struct perf_probe_event *pev,
- struct perf_probe_point *tmp,
- const char *target)
+ struct perf_probe_point *tmp)
{
int ret;

memcpy(tmp, &pev->point, sizeof(*tmp));
memset(&pev->point, 0, sizeof(pev->point));
ret = find_alternative_probe_point(dinfo, tmp, &pev->point,
- target, pev->uprobes);
+ pev->target, pev->uprobes);
if (ret < 0)
memcpy(&pev->point, tmp, sizeof(*tmp));

@@ -601,15 +600,14 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
/* Try to find perf_probe_event with debuginfo */
static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event **tevs,
- int max_tevs, const char *target)
+ int max_tevs)
{
bool need_dwarf = perf_probe_event_need_dwarf(pev);
struct perf_probe_point tmp;
struct debuginfo *dinfo;
int ntevs, ret = 0;

- dinfo = open_debuginfo(target, !need_dwarf);
-
+ dinfo = open_debuginfo(pev->target, !need_dwarf);
if (!dinfo) {
if (need_dwarf)
return -ENOENT;
@@ -622,7 +620,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);

if (ntevs == 0) { /* Not found, retry with an alternative */
- ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
+ ret = get_alternative_probe_event(dinfo, pev, &tmp);
if (!ret) {
ntevs = debuginfo__find_trace_events(dinfo, pev,
tevs, max_tevs);
@@ -640,7 +638,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
if (ntevs > 0) { /* Succeeded to find trace events */
pr_debug("Found %d probe_trace_events.\n", ntevs);
ret = post_process_probe_trace_events(*tevs, ntevs,
- target, pev->uprobes);
+ pev->target, pev->uprobes);
if (ret < 0 || ret == ntevs) {
clear_probe_trace_events(*tevs, ntevs);
zfree(tevs);
@@ -824,7 +822,7 @@ int show_line_range(struct line_range *lr, const char *module, bool user)
static int show_available_vars_at(struct debuginfo *dinfo,
struct perf_probe_event *pev,
int max_vls, struct strfilter *_filter,
- bool externs, const char *target)
+ bool externs)
{
char *buf;
int ret, i, nvars;
@@ -841,7 +839,7 @@ static int show_available_vars_at(struct debuginfo *dinfo,
ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
max_vls, externs);
if (!ret) { /* Not found, retry with an alternative */
- ret = get_alternative_probe_event(dinfo, pev, &tmp, target);
+ ret = get_alternative_probe_event(dinfo, pev, &tmp);
if (!ret) {
ret = debuginfo__find_available_vars_at(dinfo, pev,
&vls, max_vls, externs);
@@ -891,8 +889,7 @@ end:

/* Show available variables on given probe point */
int show_available_vars(struct perf_probe_event *pevs, int npevs,
- int max_vls, const char *module,
- struct strfilter *_filter, bool externs)
+ int max_vls, struct strfilter *_filter, bool externs)
{
int i, ret = 0;
struct debuginfo *dinfo;
@@ -901,7 +898,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
if (ret < 0)
return ret;

- dinfo = open_debuginfo(module, false);
+ dinfo = open_debuginfo(pevs->target, false);
if (!dinfo) {
ret = -ENOENT;
goto out;
@@ -911,7 +908,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,

for (i = 0; i < npevs && ret >= 0; i++)
ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
- externs, module);
+ externs);

debuginfo__delete(dinfo);
out:
@@ -931,8 +928,7 @@ find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused,

static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event **tevs __maybe_unused,
- int max_tevs __maybe_unused,
- const char *target __maybe_unused)
+ int max_tevs __maybe_unused)
{
if (perf_probe_event_need_dwarf(pev)) {
pr_warning("Debuginfo-analysis is not supported.\n");
@@ -952,7 +948,6 @@ int show_line_range(struct line_range *lr __maybe_unused,

int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
int npevs __maybe_unused, int max_vls __maybe_unused,
- const char *module __maybe_unused,
struct strfilter *filter __maybe_unused,
bool externs __maybe_unused)
{
@@ -2520,7 +2515,7 @@ void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
*/
static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
struct probe_trace_event **tevs,
- int max_tevs, const char *target)
+ int max_tevs)
{
struct map *map = NULL;
struct ref_reloc_sym *reloc_sym = NULL;
@@ -2531,7 +2526,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
int num_matched_functions;
int ret, i;

- map = get_target_map(target, pev->uprobes);
+ map = get_target_map(pev->target, pev->uprobes);
if (!map) {
ret = -EINVAL;
goto out;
@@ -2544,12 +2539,12 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
num_matched_functions = find_probe_functions(map, pp->function);
if (num_matched_functions == 0) {
pr_err("Failed to find symbol %s in %s\n", pp->function,
- target ? : "kernel");
+ pev->target ? : "kernel");
ret = -ENOENT;
goto out;
} else if (num_matched_functions > max_tevs) {
pr_err("Too many functions matched in %s\n",
- target ? : "kernel");
+ pev->target ? : "kernel");
ret = -E2BIG;
goto out;
}
@@ -2597,8 +2592,9 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
tp->offset = pp->offset;
}
tp->retprobe = pp->retprobe;
- if (target)
- tev->point.module = strdup_or_goto(target, nomem_out);
+ if (pev->target)
+ tev->point.module = strdup_or_goto(pev->target,
+ nomem_out);
tev->uprobes = pev->uprobes;
tev->nargs = pev->nargs;
if (tev->nargs) {
@@ -2639,13 +2635,13 @@ bool __weak arch__prefers_symtab(void) { return false; }

static int convert_to_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event **tevs,
- int max_tevs, const char *target)
+ int max_tevs)
{
int ret;

if (pev->uprobes && !pev->group) {
/* Replace group name if not given */
- ret = convert_exec_to_group(target, &pev->group);
+ ret = convert_exec_to_group(pev->target, &pev->group);
if (ret != 0) {
pr_warning("Failed to make a group name.\n");
return ret;
@@ -2653,17 +2649,17 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
}

if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
- ret = find_probe_trace_events_from_map(pev, tevs, max_tevs, target);
+ ret = find_probe_trace_events_from_map(pev, tevs, max_tevs);
if (ret > 0)
return ret; /* Found in symbol table */
}

/* Convert perf_probe_event with debuginfo */
- ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target);
+ ret = try_to_find_probe_trace_events(pev, tevs, max_tevs);
if (ret != 0)
return ret; /* Found in debuginfo or got an error */

- return find_probe_trace_events_from_map(pev, tevs, max_tevs, target);
+ return find_probe_trace_events_from_map(pev, tevs, max_tevs);
}

struct __event_package {
@@ -2696,8 +2692,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
/* Convert with or without debuginfo */
ret = convert_to_probe_trace_events(pkgs[i].pev,
&pkgs[i].tevs,
- max_tevs,
- pkgs[i].pev->target);
+ max_tevs);
if (ret < 0)
goto end;
pkgs[i].ntevs = ret;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e10aedc..e3d9bb1 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -131,8 +131,8 @@ extern int show_perf_probe_events(struct strfilter *filter);
extern int show_line_range(struct line_range *lr, const char *module,
bool user);
extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
- int max_probe_points, const char *module,
- struct strfilter *filter, bool externs);
+ int max_probe_points, struct strfilter *filter,
+ bool externs);
extern int show_available_funcs(const char *module, struct strfilter *filter,
bool user);
bool arch__prefers_symtab(void);

Subject: [tip:perf/core] perf probe: Introduce probe_conf global configs

Commit-ID: ddb2f58f9f8febaf817496a010130f108bb9a431
Gitweb: http://git.kernel.org/tip/ddb2f58f9f8febaf817496a010130f108bb9a431
Author: Masami Hiramatsu <[email protected]>
AuthorDate: Fri, 8 May 2015 10:03:31 +0900
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Fri, 8 May 2015 16:26:26 -0300

perf probe: Introduce probe_conf global configs

Introduce probe_conf global configuration parameters for probe-event and
probe-finder, and removes related parameters from APIs.

Signed-off-by: Masami Hiramatsu <[email protected]>
Cc: Ananth N Mavinakayanahalli <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Hemant Kumar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-probe.c | 21 ++++++-----------
tools/perf/util/probe-event.c | 53 ++++++++++++++++++------------------------
tools/perf/util/probe-event.h | 13 +++++++----
tools/perf/util/probe-finder.c | 17 +++++++-------
tools/perf/util/probe-finder.h | 7 ++----
5 files changed, 48 insertions(+), 63 deletions(-)

diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 233f941..dbc998f 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -50,8 +50,6 @@
static struct {
int command; /* Command short_name */
bool list_events;
- bool force_add;
- bool show_ext_vars;
bool uprobes;
bool quiet;
bool target_used;
@@ -59,7 +57,6 @@ static struct {
struct perf_probe_event events[MAX_PROBES];
struct line_range line_range;
char *target;
- int max_probe_points;
struct strfilter *filter;
} params;

@@ -364,7 +361,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
"\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
#endif
opt_add_probe_event),
- OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events"
+ OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
" with existing name"),
#ifdef HAVE_DWARF_SUPPORT
OPT_CALLBACK('L', "line", NULL,
@@ -373,7 +370,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_CALLBACK('V', "vars", NULL,
"FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
"Show accessible variables on PROBEDEF", opt_show_vars),
- OPT_BOOLEAN('\0', "externs", &params.show_ext_vars,
+ OPT_BOOLEAN('\0', "externs", &probe_conf.show_ext_vars,
"Show external variables too (with --vars only)"),
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
"file", "vmlinux pathname"),
@@ -384,7 +381,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
opt_set_target),
#endif
OPT__DRY_RUN(&probe_event_dry_run),
- OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
+ OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
"Set how many probe points can be found for a probe."),
OPT_CALLBACK_DEFAULT('F', "funcs", NULL, "[FILTER]",
"Show potential probe-able functions.",
@@ -440,8 +437,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
verbose = -1;
}

- if (params.max_probe_points == 0)
- params.max_probe_points = MAX_PROBES;
+ if (probe_conf.max_probes == 0)
+ probe_conf.max_probes = MAX_PROBES;

/*
* Only consider the user's kernel image path if given.
@@ -477,9 +474,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
NULL);

ret = show_available_vars(params.events, params.nevents,
- params.max_probe_points,
- params.filter,
- params.show_ext_vars);
+ params.filter);
if (ret < 0)
pr_err_with_code(" Error: Failed to show vars.", ret);
return ret;
@@ -498,9 +493,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
usage_with_options(probe_usage, options);
}

- ret = add_perf_probe_events(params.events, params.nevents,
- params.max_probe_points,
- params.force_add);
+ ret = add_perf_probe_events(params.events, params.nevents);
if (ret < 0) {
pr_err_with_code(" Error: Failed to add events.", ret);
return ret;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index b8fd48d..a7deda4 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -51,6 +51,7 @@
#define PERFPROBE_GROUP "probe"

bool probe_event_dry_run; /* Dry run flag */
+struct probe_conf probe_conf;

#define semantic_error(msg ...) pr_err("Semantic error :" msg)

@@ -599,8 +600,7 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,

/* Try to find perf_probe_event with debuginfo */
static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
- struct probe_trace_event **tevs,
- int max_tevs)
+ struct probe_trace_event **tevs)
{
bool need_dwarf = perf_probe_event_need_dwarf(pev);
struct perf_probe_point tmp;
@@ -617,13 +617,12 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,

pr_debug("Try to find probe point from debuginfo.\n");
/* Searching trace events corresponding to a probe event */
- ntevs = debuginfo__find_trace_events(dinfo, pev, tevs, max_tevs);
+ ntevs = debuginfo__find_trace_events(dinfo, pev, tevs);

if (ntevs == 0) { /* Not found, retry with an alternative */
ret = get_alternative_probe_event(dinfo, pev, &tmp);
if (!ret) {
- ntevs = debuginfo__find_trace_events(dinfo, pev,
- tevs, max_tevs);
+ ntevs = debuginfo__find_trace_events(dinfo, pev, tevs);
/*
* Write back to the original probe_event for
* setting appropriate (user given) event name
@@ -821,8 +820,7 @@ int show_line_range(struct line_range *lr, const char *module, bool user)

static int show_available_vars_at(struct debuginfo *dinfo,
struct perf_probe_event *pev,
- int max_vls, struct strfilter *_filter,
- bool externs)
+ struct strfilter *_filter)
{
char *buf;
int ret, i, nvars;
@@ -836,13 +834,12 @@ static int show_available_vars_at(struct debuginfo *dinfo,
return -EINVAL;
pr_debug("Searching variables at %s\n", buf);

- ret = debuginfo__find_available_vars_at(dinfo, pev, &vls,
- max_vls, externs);
+ ret = debuginfo__find_available_vars_at(dinfo, pev, &vls);
if (!ret) { /* Not found, retry with an alternative */
ret = get_alternative_probe_event(dinfo, pev, &tmp);
if (!ret) {
ret = debuginfo__find_available_vars_at(dinfo, pev,
- &vls, max_vls, externs);
+ &vls);
/* Release the old probe_point */
clear_perf_probe_point(&tmp);
}
@@ -889,7 +886,7 @@ end:

/* Show available variables on given probe point */
int show_available_vars(struct perf_probe_event *pevs, int npevs,
- int max_vls, struct strfilter *_filter, bool externs)
+ struct strfilter *_filter)
{
int i, ret = 0;
struct debuginfo *dinfo;
@@ -907,8 +904,7 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
setup_pager();

for (i = 0; i < npevs && ret >= 0; i++)
- ret = show_available_vars_at(dinfo, &pevs[i], max_vls, _filter,
- externs);
+ ret = show_available_vars_at(dinfo, &pevs[i], _filter);

debuginfo__delete(dinfo);
out:
@@ -927,8 +923,7 @@ find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused,
}

static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
- struct probe_trace_event **tevs __maybe_unused,
- int max_tevs __maybe_unused)
+ struct probe_trace_event **tevs __maybe_unused)
{
if (perf_probe_event_need_dwarf(pev)) {
pr_warning("Debuginfo-analysis is not supported.\n");
@@ -947,9 +942,8 @@ int show_line_range(struct line_range *lr __maybe_unused,
}

int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
- int npevs __maybe_unused, int max_vls __maybe_unused,
- struct strfilter *filter __maybe_unused,
- bool externs __maybe_unused)
+ int npevs __maybe_unused,
+ struct strfilter *filter __maybe_unused)
{
pr_warning("Debuginfo-analysis is not supported.\n");
return -ENOSYS;
@@ -2514,8 +2508,7 @@ void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
* Return an error or the number of found probe_trace_event
*/
static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
- struct probe_trace_event **tevs,
- int max_tevs)
+ struct probe_trace_event **tevs)
{
struct map *map = NULL;
struct ref_reloc_sym *reloc_sym = NULL;
@@ -2542,7 +2535,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
pev->target ? : "kernel");
ret = -ENOENT;
goto out;
- } else if (num_matched_functions > max_tevs) {
+ } else if (num_matched_functions > probe_conf.max_probes) {
pr_err("Too many functions matched in %s\n",
pev->target ? : "kernel");
ret = -E2BIG;
@@ -2634,8 +2627,7 @@ err_out:
bool __weak arch__prefers_symtab(void) { return false; }

static int convert_to_probe_trace_events(struct perf_probe_event *pev,
- struct probe_trace_event **tevs,
- int max_tevs)
+ struct probe_trace_event **tevs)
{
int ret;

@@ -2649,17 +2641,17 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
}

if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
- ret = find_probe_trace_events_from_map(pev, tevs, max_tevs);
+ ret = find_probe_trace_events_from_map(pev, tevs);
if (ret > 0)
return ret; /* Found in symbol table */
}

/* Convert perf_probe_event with debuginfo */
- ret = try_to_find_probe_trace_events(pev, tevs, max_tevs);
+ ret = try_to_find_probe_trace_events(pev, tevs);
if (ret != 0)
return ret; /* Found in debuginfo or got an error */

- return find_probe_trace_events_from_map(pev, tevs, max_tevs);
+ return find_probe_trace_events_from_map(pev, tevs);
}

struct __event_package {
@@ -2668,8 +2660,7 @@ struct __event_package {
int ntevs;
};

-int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
- int max_tevs, bool force_add)
+int add_perf_probe_events(struct perf_probe_event *pevs, int npevs)
{
int i, j, ret;
struct __event_package *pkgs;
@@ -2691,8 +2682,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
pkgs[i].pev = &pevs[i];
/* Convert with or without debuginfo */
ret = convert_to_probe_trace_events(pkgs[i].pev,
- &pkgs[i].tevs,
- max_tevs);
+ &pkgs[i].tevs);
if (ret < 0)
goto end;
pkgs[i].ntevs = ret;
@@ -2701,7 +2691,8 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
/* Loop 2: add all events */
for (i = 0; i < npevs; i++) {
ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
- pkgs[i].ntevs, force_add);
+ pkgs[i].ntevs,
+ probe_conf.force_add);
if (ret < 0)
break;
}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e3d9bb1..db9a9cb2 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -6,6 +6,13 @@
#include "strlist.h"
#include "strfilter.h"

+/* Probe related configurations */
+struct probe_conf {
+ bool show_ext_vars;
+ bool force_add;
+ int max_probes;
+};
+extern struct probe_conf probe_conf;
extern bool probe_event_dry_run;

/* kprobe-tracer and uprobe-tracer tracing point */
@@ -124,15 +131,13 @@ extern int line_range__init(struct line_range *lr);
/* Internal use: Return kernel/module path */
extern const char *kernel_get_module_path(const char *module);

-extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
- int max_probe_points, bool force_add);
+extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
extern int del_perf_probe_events(struct strfilter *filter);
extern int show_perf_probe_events(struct strfilter *filter);
extern int show_line_range(struct line_range *lr, const char *module,
bool user);
extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
- int max_probe_points, struct strfilter *filter,
- bool externs);
+ struct strfilter *filter);
extern int show_available_funcs(const char *module, struct strfilter *filter,
bool user);
bool arch__prefers_symtab(void);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 63d3389..f4f5eed 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1214,15 +1214,15 @@ end:
/* Find probe_trace_events specified by perf_probe_event from debuginfo */
int debuginfo__find_trace_events(struct debuginfo *dbg,
struct perf_probe_event *pev,
- struct probe_trace_event **tevs, int max_tevs)
+ struct probe_trace_event **tevs)
{
struct trace_event_finder tf = {
.pf = {.pev = pev, .callback = add_probe_trace_event},
- .mod = dbg->mod, .max_tevs = max_tevs};
+ .max_tevs = probe_conf.max_probes, .mod = dbg->mod};
int ret;

/* Allocate result tevs array */
- *tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs);
+ *tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs);
if (*tevs == NULL)
return -ENOMEM;

@@ -1303,9 +1303,9 @@ static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf)
die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem);

/* Find external variables */
- if (!af->externs)
+ if (!probe_conf.show_ext_vars)
goto out;
- /* Don't need to search child DIE for externs. */
+ /* Don't need to search child DIE for external vars. */
af->child = false;
die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem);

@@ -1325,17 +1325,16 @@ out:
*/
int debuginfo__find_available_vars_at(struct debuginfo *dbg,
struct perf_probe_event *pev,
- struct variable_list **vls,
- int max_vls, bool externs)
+ struct variable_list **vls)
{
struct available_var_finder af = {
.pf = {.pev = pev, .callback = add_available_vars},
.mod = dbg->mod,
- .max_vls = max_vls, .externs = externs};
+ .max_vls = probe_conf.max_probes};
int ret;

/* Allocate result vls array */
- *vls = zalloc(sizeof(struct variable_list) * max_vls);
+ *vls = zalloc(sizeof(struct variable_list) * af.max_vls);
if (*vls == NULL)
return -ENOMEM;

diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index f53553d..bed8271 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -40,8 +40,7 @@ extern void debuginfo__delete(struct debuginfo *dbg);
/* Find probe_trace_events specified by perf_probe_event from debuginfo */
extern int debuginfo__find_trace_events(struct debuginfo *dbg,
struct perf_probe_event *pev,
- struct probe_trace_event **tevs,
- int max_tevs);
+ struct probe_trace_event **tevs);

/* Find a perf_probe_point from debuginfo */
extern int debuginfo__find_probe_point(struct debuginfo *dbg,
@@ -55,8 +54,7 @@ extern int debuginfo__find_line_range(struct debuginfo *dbg,
/* Find available variables */
extern int debuginfo__find_available_vars_at(struct debuginfo *dbg,
struct perf_probe_event *pev,
- struct variable_list **vls,
- int max_points, bool externs);
+ struct variable_list **vls);

/* Find a src file from a DWARF tag path */
int get_real_path(const char *raw_path, const char *comp_dir,
@@ -99,7 +97,6 @@ struct available_var_finder {
struct variable_list *vls; /* Found variable lists */
int nvls; /* Number of variable lists */
int max_vls; /* Max no. of variable lists */
- bool externs; /* Find external vars too */
bool child; /* Search child scopes */
};

Subject: [tip:perf/core] perf probe: Add --no-inlines option to avoid searching inline functions

Commit-ID: 6cfd1f6805ca0b4a341794d67eb605089435f938
Gitweb: http://git.kernel.org/tip/6cfd1f6805ca0b4a341794d67eb605089435f938
Author: Masami Hiramatsu <[email protected]>
AuthorDate: Fri, 8 May 2015 10:03:33 +0900
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Fri, 8 May 2015 16:26:44 -0300

perf probe: Add --no-inlines option to avoid searching inline functions

Add --no-inlines(--inlines) option to avoid searching inline functions.

Searching all functions which matches glob pattern can take a long time
and find a lot of inline functions.

With this option perf-probe searches target on the non-inlined
functions.

Signed-off-by: Masami Hiramatsu <[email protected]>
Cc: Ananth N Mavinakayanahalli <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Hemant Kumar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/perf-probe.txt | 4 ++++
tools/perf/builtin-probe.c | 2 ++
tools/perf/util/probe-event.h | 1 +
tools/perf/util/probe-finder.c | 2 +-
4 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index ad3e355..3a8a9ba 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -83,6 +83,10 @@ OPTIONS
(Only for --vars) Show external defined variables in addition to local
variables.

+--no-inlines::
+ (Only for --add) Search only for non-inlined functions. The functions
+ which do not have instances are ignored.
+
-F::
--funcs[=FILTER]::
Show available functions in given module or kernel. With -x/--exec,
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index dbc998f..7fa2c7a 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -379,6 +379,8 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_CALLBACK('m', "module", NULL, "modname|path",
"target module name (for online) or path (for offline)",
opt_set_target),
+ OPT_BOOLEAN('\0', "no-inlines", &probe_conf.no_inlines,
+ "Don't search inlined functions"),
#endif
OPT__DRY_RUN(&probe_event_dry_run),
OPT_INTEGER('\0', "max-probes", &probe_conf.max_probes,
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index db9a9cb2..633aba7 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -10,6 +10,7 @@
struct probe_conf {
bool show_ext_vars;
bool force_add;
+ bool no_inlines;
int max_probes;
};
extern struct probe_conf probe_conf;
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index f4f5eed..1713421 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -943,7 +943,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
/* TODO: Check the address in this function */
param->retval = call_probe_finder(sp_die, pf);
}
- } else
+ } else if (!probe_conf.no_inlines)
/* Inlined function: search instances */
param->retval = die_walk_instances(sp_die,
probe_point_inline_cb, (void *)pf);

Subject: [tip:perf/core] perf probe: Support glob wildcards for function name

Commit-ID: 4c859351226c920b227fec040a3b447f0d482af3
Gitweb: http://git.kernel.org/tip/4c859351226c920b227fec040a3b447f0d482af3
Author: Masami Hiramatsu <[email protected]>
AuthorDate: Fri, 8 May 2015 10:03:35 +0900
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Fri, 8 May 2015 16:31:02 -0300

perf probe: Support glob wildcards for function name

Support glob wildcards for function name when adding new probes. This
will allow us to build caches of function-entry level information with
$params.

e.g.
----
# perf probe --no-inlines --add 'kmalloc* $params'
Added new events:
probe:kmalloc_slab (on kmalloc* with $params)
probe:kmalloc_large_node (on kmalloc* with $params)
probe:kmalloc_order_trace (on kmalloc* with $params)

You can now use it in all perf tools, such as:

perf record -e probe:kmalloc_order_trace -aR sleep 1

# perf probe --list
probe:kmalloc_large_node (on kmalloc_large_node@mm/slub.c with size flags node)
probe:kmalloc_order_trace (on kmalloc_order_trace@mm/slub.c with size flags order)
probe:kmalloc_slab (on kmalloc_slab@mm/slab_common.c with size flags)
----

Signed-off-by: Masami Hiramatsu <[email protected]>
Tested-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Ananth N Mavinakayanahalli <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Hemant Kumar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/dwarf-aux.c | 16 ++++++++++++++++
tools/perf/util/dwarf-aux.h | 3 +++
tools/perf/util/probe-event.c | 19 ++++++++++++++-----
tools/perf/util/probe-event.h | 1 +
tools/perf/util/probe-finder.c | 27 +++++++++++++++++++++------
tools/perf/util/util.h | 4 ++++
6 files changed, 59 insertions(+), 11 deletions(-)

diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index c34e024..16d46e2 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -139,11 +139,27 @@ int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
{
const char *name;
+
name = dwarf_diename(dw_die);
return name ? (strcmp(tname, name) == 0) : false;
}

/**
+ * die_match_name - Match diename and glob
+ * @dw_die: a DIE
+ * @glob: a string of target glob pattern
+ *
+ * Glob matching the name of @dw_die and @glob. Return false if matching fail.
+ */
+bool die_match_name(Dwarf_Die *dw_die, const char *glob)
+{
+ const char *name;
+
+ name = dwarf_diename(dw_die);
+ return name ? strglobmatch(name, glob) : false;
+}
+
+/**
* die_get_call_lineno - Get callsite line number of inline-function instance
* @in_die: a DIE of an inlined function instance
*
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index af7dbcd..50a3cdc 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -47,6 +47,9 @@ extern bool die_is_func_instance(Dwarf_Die *dw_die);
/* Compare diename and tname */
extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname);

+/* Matching diename with glob pattern */
+extern bool die_match_name(Dwarf_Die *dw_die, const char *glob);
+
/* Get callsite line number of inline-function instance */
extern int die_get_call_lineno(Dwarf_Die *in_die);

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index a7deda4..a2d8cef 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -589,7 +589,11 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
if (!tmp)
return -ENOMEM;
}
- free(tevs[i].point.symbol);
+ /* If we have no realname, use symbol for it */
+ if (!tevs[i].point.realname)
+ tevs[i].point.realname = tevs[i].point.symbol;
+ else
+ free(tevs[i].point.symbol);
tevs[i].point.symbol = tmp;
tevs[i].point.offset = tevs[i].point.address -
reloc_sym->unrelocated_addr;
@@ -1900,6 +1904,7 @@ static void clear_probe_trace_event(struct probe_trace_event *tev)
free(tev->event);
free(tev->group);
free(tev->point.symbol);
+ free(tev->point.realname);
free(tev->point.module);
for (i = 0; i < tev->nargs; i++) {
free(tev->args[i].name);
@@ -2377,6 +2382,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
struct strlist *namelist;
LIST_HEAD(blacklist);
struct kprobe_blacklist_node *node;
+ bool safename;

if (pev->uprobes)
fd = open_uprobe_events(true);
@@ -2402,6 +2408,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
pr_debug("No kprobe blacklist support, ignored\n");
}

+ safename = (pev->point.function && !strisglob(pev->point.function));
ret = 0;
pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
for (i = 0; i < ntevs; i++) {
@@ -2420,10 +2427,10 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
if (pev->event)
event = pev->event;
else
- if (pev->point.function)
+ if (safename)
event = pev->point.function;
else
- event = tev->point.symbol;
+ event = tev->point.realname;
if (pev->group)
group = pev->group;
else
@@ -2488,9 +2495,11 @@ static int find_probe_functions(struct map *map, char *name)
{
int found = 0;
struct symbol *sym;
+ struct rb_node *tmp;

- map__for_each_symbol_by_name(map, name, sym) {
- found++;
+ map__for_each_symbol(map, sym, tmp) {
+ if (strglobmatch(sym->name, name))
+ found++;
}

return found;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 633aba7..1e2faa3 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -18,6 +18,7 @@ extern bool probe_event_dry_run;

/* kprobe-tracer and uprobe-tracer tracing point */
struct probe_trace_point {
+ char *realname; /* function real name (if needed) */
char *symbol; /* Base symbol */
char *module; /* Module name */
unsigned long offset; /* Offset from symbol */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 1713421..d5f60c0 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -717,7 +717,7 @@ static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
}
/* If the function name is given, that's what user expects */
if (fsp->function) {
- if (die_compare_name(fn_die, fsp->function)) {
+ if (die_match_name(fn_die, fsp->function)) {
memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
fsp->found = true;
return 1;
@@ -920,13 +920,14 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)

/* Check tag and diename */
if (!die_is_func_def(sp_die) ||
- !die_compare_name(sp_die, pp->function))
+ !die_match_name(sp_die, pp->function))
return DWARF_CB_OK;

/* Check declared file */
if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
return DWARF_CB_OK;

+ pr_debug("Matched function: %s\n", dwarf_diename(sp_die));
pf->fname = dwarf_decl_file(sp_die);
if (pp->line) { /* Function relative line */
dwarf_decl_line(sp_die, &pf->lno);
@@ -943,10 +944,20 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
/* TODO: Check the address in this function */
param->retval = call_probe_finder(sp_die, pf);
}
- } else if (!probe_conf.no_inlines)
+ } else if (!probe_conf.no_inlines) {
/* Inlined function: search instances */
param->retval = die_walk_instances(sp_die,
probe_point_inline_cb, (void *)pf);
+ /* This could be a non-existed inline definition */
+ if (param->retval == -ENOENT && strisglob(pp->function))
+ param->retval = 0;
+ }
+
+ /* We need to find other candidates */
+ if (strisglob(pp->function) && param->retval >= 0) {
+ param->retval = 0; /* We have to clear the result */
+ return DWARF_CB_OK;
+ }

return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */
}
@@ -975,7 +986,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
return DWARF_CB_OK;

- if (die_compare_name(param->sp_die, param->function)) {
+ if (die_match_name(param->sp_die, param->function)) {
if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
return DWARF_CB_OK;

@@ -1028,7 +1039,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
return -ENOMEM;

/* Fastpath: lookup by function name from .debug_pubnames section */
- if (pp->function) {
+ if (pp->function && !strisglob(pp->function)) {
struct pubname_callback_param pubname_param = {
.function = pp->function,
.file = pp->file,
@@ -1177,6 +1188,10 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
if (ret < 0)
return ret;

+ tev->point.realname = strdup(dwarf_diename(sc_die));
+ if (!tev->point.realname)
+ return -ENOMEM;
+
pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
tev->point.offset);

@@ -1535,7 +1550,7 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
return DWARF_CB_OK;

if (die_is_func_def(sp_die) &&
- die_compare_name(sp_die, lr->function)) {
+ die_match_name(sp_die, lr->function)) {
lf->fname = dwarf_decl_file(sp_die);
dwarf_decl_line(sp_die, &lr->offset);
pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 1ff23e0..3601ffd 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -257,6 +257,10 @@ char **argv_split(const char *str, int *argcp);
void argv_free(char **argv);
bool strglobmatch(const char *str, const char *pat);
bool strlazymatch(const char *str, const char *pat);
+static inline bool strisglob(const char *str)
+{
+ return strpbrk(str, "*?[") != NULL;
+}
int strtailcmp(const char *s1, const char *s2);
char *strxfrchar(char *s, char from, char to);
unsigned long convert_unit(unsigned long value, char *unit);