2010-04-21 19:50:47

by Masami Hiramatsu

[permalink] [raw]
Subject: [PATCH -tip 1/4] [BUGFIX] perf tools: Initialize dso->node member in dso__new

If dso->node member is not initilized, it causes a segmentation
fault when adding to other lists. It should be initilized in
dso__new().

Signed-off-by: Masami Hiramatsu <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
---

tools/perf/util/symbol.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e782e7d..e77c33a 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -189,6 +189,7 @@ struct dso *dso__new(const char *name)
self->sorted_by_name = 0;
self->has_build_id = 0;
self->kernel = DSO_TYPE_USER;
+ INIT_LIST_HEAD(&self->node);
}

return self;


--
Masami Hiramatsu
e-mail: [email protected]


2010-04-21 19:50:23

by Masami Hiramatsu

[permalink] [raw]
Subject: [PATCH -tip 2/4] perf probe: Fix to use symtab only if no debuginfo

Fix perf probe to use symtab only if there is no debuginfo,
because debuginfo has more precise information than symtab.
If we can't find a function in debuginfo, we never find it
in symtab.

Signed-off-by: Masami Hiramatsu <[email protected]>
Reported-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
---

tools/perf/util/probe-event.c | 17 +++++++++--------
1 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 4fb4803..5d3baec 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -180,15 +180,16 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
return -ENOENT;
}
/* Error path : ntevs < 0 */
- if (need_dwarf) {
- if (ntevs == -EBADF)
- pr_warning("No dwarf info found in the vmlinux - "
- "please rebuild with CONFIG_DEBUG_INFO=y.\n");
- return ntevs;
+ pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
+ if (ntevs == -EBADF) {
+ pr_warning("Warning: No dwarf info found in the vmlinux - "
+ "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
+ if (!need_dwarf) {
+ pr_debug("Trying to use symbols.\nn");
+ return 0;
+ }
}
- pr_debug("An error occurred in debuginfo analysis."
- " Try to use symbols.\n");
- return 0;
+ return ntevs;
}

#define LINEBUF_SIZE 256


--
Masami Hiramatsu
e-mail: [email protected]

2010-04-21 19:50:44

by Masami Hiramatsu

[permalink] [raw]
Subject: [PATCH -tip 4/4] perf probe: Add --max-probes option

Add --max-probes option to change the maximum limit of
findable probe points per event, since inlined function can be
expanded into thousands of probe points. Default value is 128.

Signed-off-by: Masami Hiramatsu <[email protected]>
Suggested-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
---

tools/perf/Documentation/perf-probe.txt | 3 +++
tools/perf/builtin-probe.c | 9 ++++++++-
tools/perf/util/probe-event.c | 17 ++++++++++-------
tools/perf/util/probe-event.h | 4 ++--
tools/perf/util/probe-finder.c | 11 ++++++-----
tools/perf/util/probe-finder.h | 6 ++++--
6 files changed, 33 insertions(+), 17 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 63c25d3..94a258c 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -62,6 +62,9 @@ OPTIONS
Dry run. With this option, --add and --del doesn't execute actual
adding and removal operations.

+--max-probes::
+ Set the maximum number of probe points for an event. Default is 128.
+
PROBE SYNTAX
------------
Probe points are defined by following syntax.
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index c1e5403..61c6d70 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -54,6 +54,7 @@ static struct {
struct perf_probe_event events[MAX_PROBES];
struct strlist *dellist;
struct line_range line_range;
+ int max_probe_points;
} params;


@@ -179,6 +180,8 @@ static const struct option options[] = {
"file", "vmlinux pathname"),
#endif
OPT__DRY_RUN(&probe_event_dry_run),
+ OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
+ "Set how many probe points can be found for a probe."),
OPT_END()
};

@@ -200,6 +203,9 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
}
}

+ if (params.max_probe_points == 0)
+ params.max_probe_points = MAX_PROBES;
+
if ((!params.nevents && !params.dellist && !params.list_events &&
!params.show_lines))
usage_with_options(probe_usage, options);
@@ -246,7 +252,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)

if (params.nevents) {
ret = add_perf_probe_events(params.events, params.nevents,
- params.force_add);
+ params.force_add,
+ params.max_probe_points);
if (ret < 0) {
pr_err(" Error: Failed to add events. (%d)\n", ret);
return ret;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 5d3baec..9ded38c 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -150,7 +150,8 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,

/* Try to find perf_probe_event with debuginfo */
static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
- struct kprobe_trace_event **tevs)
+ struct kprobe_trace_event **tevs,
+ int max_tevs)
{
bool need_dwarf = perf_probe_event_need_dwarf(pev);
int fd, ntevs;
@@ -166,7 +167,7 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
}

/* Searching trace events corresponding to probe event */
- ntevs = find_kprobe_trace_events(fd, pev, tevs);
+ ntevs = find_kprobe_trace_events(fd, pev, tevs, max_tevs);
close(fd);

if (ntevs > 0) { /* Succeeded to find trace events */
@@ -318,7 +319,8 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
}

static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
- struct kprobe_trace_event **tevs __unused)
+ struct kprobe_trace_event **tevs __unused,
+ int max_tevs __unused)
{
if (perf_probe_event_need_dwarf(pev)) {
pr_warning("Debuginfo-analysis is not supported.\n");
@@ -1408,14 +1410,15 @@ static int __add_kprobe_trace_events(struct perf_probe_event *pev,
}

static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
- struct kprobe_trace_event **tevs)
+ struct kprobe_trace_event **tevs,
+ int max_tevs)
{
struct symbol *sym;
int ret = 0, i;
struct kprobe_trace_event *tev;

/* Convert perf_probe_event with debuginfo */
- ret = try_to_find_kprobe_trace_events(pev, tevs);
+ ret = try_to_find_kprobe_trace_events(pev, tevs, max_tevs);
if (ret != 0)
return ret;

@@ -1487,7 +1490,7 @@ struct __event_package {
};

int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
- bool force_add)
+ bool force_add, int max_tevs)
{
int i, j, ret;
struct __event_package *pkgs;
@@ -1506,7 +1509,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_kprobe_trace_events(pkgs[i].pev,
- &pkgs[i].tevs);
+ &pkgs[i].tevs, 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 e7ff0d0..e9db1a2 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -115,8 +115,8 @@ extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev);
extern int parse_line_range_desc(const char *cmd, struct line_range *lr);


-extern int add_perf_probe_events(struct perf_probe_event *pevs, int ntevs,
- bool force_add);
+extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
+ bool force_add, int max_probe_points);
extern int del_perf_probe_events(struct strlist *dellist);
extern int show_perf_probe_events(void);
extern int show_line_range(struct line_range *lr);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 57b51ca..e3e3c1e 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -677,8 +677,9 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
Dwarf_Attribute fb_attr;
size_t nops;

- if (pf->ntevs == MAX_PROBES) {
- pr_warning("Too many( > %d) probe point found.\n", MAX_PROBES);
+ if (pf->ntevs == pf->max_tevs) {
+ pr_warning("Too many( > %d) probe point found.\n",
+ pf->max_tevs);
return -ERANGE;
}
tev = &pf->tevs[pf->ntevs++];
@@ -983,9 +984,9 @@ static int find_probe_point_by_func(struct probe_finder *pf)

/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
- struct kprobe_trace_event **tevs)
+ struct kprobe_trace_event **tevs, int max_tevs)
{
- struct probe_finder pf = {.pev = pev};
+ struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs};
struct perf_probe_point *pp = &pev->point;
Dwarf_Off off, noff;
size_t cuhl;
@@ -993,7 +994,7 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
Dwarf *dbg;
int ret = 0;

- pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES);
+ pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * max_tevs);
if (pf.tevs == NULL)
return -ENOMEM;
*tevs = pf.tevs;
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 310ce89..66f1980 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -18,7 +18,8 @@ static inline int is_c_varname(const char *name)
#ifdef DWARF_SUPPORT
/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
extern int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
- struct kprobe_trace_event **tevs);
+ struct kprobe_trace_event **tevs,
+ int max_tevs);

/* Find a perf_probe_point from debuginfo */
extern int find_perf_probe_point(int fd, unsigned long addr,
@@ -32,7 +33,8 @@ extern int find_line_range(int fd, struct line_range *lr);
struct probe_finder {
struct perf_probe_event *pev; /* Target probe event */
struct kprobe_trace_event *tevs; /* Result trace events */
- int ntevs; /* number of trace events */
+ int ntevs; /* Number of trace events */
+ int max_tevs; /* Max number of trace events */

/* For function searching */
int lno; /* Line number */


--
Masami Hiramatsu
e-mail: [email protected]

2010-04-21 19:50:56

by Masami Hiramatsu

[permalink] [raw]
Subject: [PATCH -tip 3/4] perf probe: Fix to exit callback soon after finding too many probe points

Fix to exit callback soon after finding too many probe points.
Don't try to continue searching because it already failed.

Signed-off-by: Masami Hiramatsu <[email protected]>
Reported-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
---

tools/perf/util/probe-finder.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 3e79775..57b51ca 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -922,6 +922,8 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
(uintmax_t)pf->addr);

param->retval = convert_probe_point(in_die, pf);
+ if (param->retval < 0)
+ return DWARF_CB_ABORT;
}

return DWARF_CB_OK;
@@ -1157,6 +1159,8 @@ static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data)
return DWARF_CB_OK;

param->retval = line_range_add_line(src, lineno, lf->lr);
+ if (param->retval < 0)
+ return DWARF_CB_ABORT;
return DWARF_CB_OK;
}



--
Masami Hiramatsu
e-mail: [email protected]

2010-04-26 12:49:13

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH -tip 2/4] perf probe: Fix to use symtab only if no debuginfo

Em Wed, Apr 21, 2010 at 03:56:24PM -0400, Masami Hiramatsu escreveu:
> Fix perf probe to use symtab only if there is no debuginfo,
> because debuginfo has more precise information than symtab.

"more precise"? Wouldn't it be "more expressive", i.e. with more
information (parameter list with types, return type, location of
parameters, etc), because what is common to both have the same value,
i.e. the function address and size.

> If we can't find a function in debuginfo, we never find it
> in symtab.
>
> Signed-off-by: Masami Hiramatsu <[email protected]>
> Reported-by: Arnaldo Carvalho de Melo <[email protected]>
> Cc: Paul Mackerras <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Cc: Mike Galbraith <[email protected]>
> Cc: Frederic Weisbecker <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> ---
>
> tools/perf/util/probe-event.c | 17 +++++++++--------
> 1 files changed, 9 insertions(+), 8 deletions(-)
>
> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> index 4fb4803..5d3baec 100644
> --- a/tools/perf/util/probe-event.c
> +++ b/tools/perf/util/probe-event.c
> @@ -180,15 +180,16 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
> return -ENOENT;
> }
> /* Error path : ntevs < 0 */
> - if (need_dwarf) {
> - if (ntevs == -EBADF)
> - pr_warning("No dwarf info found in the vmlinux - "
> - "please rebuild with CONFIG_DEBUG_INFO=y.\n");
> - return ntevs;
> + pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
> + if (ntevs == -EBADF) {
> + pr_warning("Warning: No dwarf info found in the vmlinux - "
> + "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
> + if (!need_dwarf) {
> + pr_debug("Trying to use symbols.\nn");
> + return 0;
> + }
> }
> - pr_debug("An error occurred in debuginfo analysis."
> - " Try to use symbols.\n");
> - return 0;
> + return ntevs;
> }
>
> #define LINEBUF_SIZE 256
>
>
> --
> Masami Hiramatsu
> e-mail: [email protected]

2010-04-26 14:02:49

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH -tip 1/4] [BUGFIX] perf tools: Initialize dso->node member in dso__new

Em Wed, Apr 21, 2010 at 03:56:16PM -0400, Masami Hiramatsu escreveu:
> If dso->node member is not initilized, it causes a segmentation
> fault when adding to other lists. It should be initilized in
> dso__new().
>
> Signed-off-by: Masami Hiramatsu <[email protected]>
> Cc: Arnaldo Carvalho de Melo <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Cc: Paul Mackerras <[email protected]>
> Cc: Mike Galbraith <[email protected]>
> Cc: Frederic Weisbecker <[email protected]>
> Cc: Ingo Molnar <[email protected]>
> ---
>
> tools/perf/util/symbol.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index e782e7d..e77c33a 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -189,6 +189,7 @@ struct dso *dso__new(const char *name)
> self->sorted_by_name = 0;
> self->has_build_id = 0;
> self->kernel = DSO_TYPE_USER;
> + INIT_LIST_HEAD(&self->node);
> }
>
> return self;

Trying to understand how this would be a problem, as:

static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}

This is not a list head, just a node.

Looking at other messages where you described the problem to try to
understand why this would help.

- Arnaldo

2010-04-26 19:00:34

by Masami Hiramatsu

[permalink] [raw]
Subject: Re: [PATCH -tip 2/4] perf probe: Fix to use symtab only if no debuginfo

Arnaldo Carvalho de Melo wrote:
> Em Wed, Apr 21, 2010 at 03:56:24PM -0400, Masami Hiramatsu escreveu:
>> Fix perf probe to use symtab only if there is no debuginfo,
>> because debuginfo has more precise information than symtab.
>
> "more precise"? Wouldn't it be "more expressive", i.e. with more
> information (parameter list with types, return type, location of
> parameters, etc), because what is common to both have the same value,
> i.e. the function address and size.

Indeed. debuginfo has just more information than symtab, but
symtab certainly provides precise information for symbol-address.

Thank you,


--
Masami Hiramatsu
e-mail: [email protected]

2010-04-26 19:08:27

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH -tip 2/4] perf probe: Fix to use symtab only if no debuginfo

Em Mon, Apr 26, 2010 at 02:59:36PM -0400, Masami Hiramatsu escreveu:
> Arnaldo Carvalho de Melo wrote:
> > Em Wed, Apr 21, 2010 at 03:56:24PM -0400, Masami Hiramatsu escreveu:
> >> Fix perf probe to use symtab only if there is no debuginfo,
> >> because debuginfo has more precise information than symtab.
> >
> > "more precise"? Wouldn't it be "more expressive", i.e. with more
> > information (parameter list with types, return type, location of
> > parameters, etc), because what is common to both have the same value,
> > i.e. the function address and size.
>
> Indeed. debuginfo has just more information than symtab, but
> symtab certainly provides precise information for symbol-address.

I applied the patch, just replaced "more precise information" with "more
information".

- Arnaldo

2010-04-26 19:11:27

by Masami Hiramatsu

[permalink] [raw]
Subject: Re: [PATCH -tip 2/4] perf probe: Fix to use symtab only if no debuginfo

Arnaldo Carvalho de Melo wrote:
> Em Mon, Apr 26, 2010 at 02:59:36PM -0400, Masami Hiramatsu escreveu:
>> Arnaldo Carvalho de Melo wrote:
>>> Em Wed, Apr 21, 2010 at 03:56:24PM -0400, Masami Hiramatsu escreveu:
>>>> Fix perf probe to use symtab only if there is no debuginfo,
>>>> because debuginfo has more precise information than symtab.
>>>
>>> "more precise"? Wouldn't it be "more expressive", i.e. with more
>>> information (parameter list with types, return type, location of
>>> parameters, etc), because what is common to both have the same value,
>>> i.e. the function address and size.
>>
>> Indeed. debuginfo has just more information than symtab, but
>> symtab certainly provides precise information for symbol-address.
>
> I applied the patch, just replaced "more precise information" with "more
> information".

Thank you very much! :)

>
> - 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
e-mail: [email protected]

2010-04-27 12:58:59

by Masami Hiramatsu

[permalink] [raw]
Subject: [tip:perf/core] perf probe: Fix to use symtab only if no debuginfo

Commit-ID: 15eca306ec95e164d05457f9f27c722f69af6d18
Gitweb: http://git.kernel.org/tip/15eca306ec95e164d05457f9f27c722f69af6d18
Author: Masami Hiramatsu <[email protected]>
AuthorDate: Wed, 21 Apr 2010 15:56:24 -0400
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Mon, 26 Apr 2010 15:32:37 -0300

perf probe: Fix to use symtab only if no debuginfo

Fix perf probe to use symtab only if there is no debuginfo, because debuginfo
has more information than symtab.

If we can't find a function in debuginfo, we never find it in symtab.

Signed-off-by: Masami Hiramatsu <[email protected]>
Reported-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/probe-event.c | 17 +++++++++--------
1 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 4fb4803..5d3baec 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -180,15 +180,16 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
return -ENOENT;
}
/* Error path : ntevs < 0 */
- if (need_dwarf) {
- if (ntevs == -EBADF)
- pr_warning("No dwarf info found in the vmlinux - "
- "please rebuild with CONFIG_DEBUG_INFO=y.\n");
- return ntevs;
+ pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
+ if (ntevs == -EBADF) {
+ pr_warning("Warning: No dwarf info found in the vmlinux - "
+ "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
+ if (!need_dwarf) {
+ pr_debug("Trying to use symbols.\nn");
+ return 0;
+ }
}
- pr_debug("An error occurred in debuginfo analysis."
- " Try to use symbols.\n");
- return 0;
+ return ntevs;
}

#define LINEBUF_SIZE 256

2010-04-27 12:59:34

by Masami Hiramatsu

[permalink] [raw]
Subject: [tip:perf/core] perf probe: Add --max-probes option

Commit-ID: ef4a356574426877d569f8b6579325537eb7909b
Gitweb: http://git.kernel.org/tip/ef4a356574426877d569f8b6579325537eb7909b
Author: Masami Hiramatsu <[email protected]>
AuthorDate: Wed, 21 Apr 2010 15:56:40 -0400
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Mon, 26 Apr 2010 15:35:20 -0300

perf probe: Add --max-probes option

Add --max-probes option to change the maximum limit of
findable probe points per event, since inlined function can be
expanded into thousands of probe points. Default value is 128.

Signed-off-by: Masami Hiramatsu <[email protected]>
Suggested-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/perf-probe.txt | 3 +++
tools/perf/builtin-probe.c | 9 ++++++++-
tools/perf/util/probe-event.c | 17 ++++++++++-------
tools/perf/util/probe-event.h | 4 ++--
tools/perf/util/probe-finder.c | 11 ++++++-----
tools/perf/util/probe-finder.h | 6 ++++--
6 files changed, 33 insertions(+), 17 deletions(-)

diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 63c25d3..94a258c 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -62,6 +62,9 @@ OPTIONS
Dry run. With this option, --add and --del doesn't execute actual
adding and removal operations.

+--max-probes::
+ Set the maximum number of probe points for an event. Default is 128.
+
PROBE SYNTAX
------------
Probe points are defined by following syntax.
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index c1e5403..61c6d70 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -54,6 +54,7 @@ static struct {
struct perf_probe_event events[MAX_PROBES];
struct strlist *dellist;
struct line_range line_range;
+ int max_probe_points;
} params;


@@ -179,6 +180,8 @@ static const struct option options[] = {
"file", "vmlinux pathname"),
#endif
OPT__DRY_RUN(&probe_event_dry_run),
+ OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
+ "Set how many probe points can be found for a probe."),
OPT_END()
};

@@ -200,6 +203,9 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
}
}

+ if (params.max_probe_points == 0)
+ params.max_probe_points = MAX_PROBES;
+
if ((!params.nevents && !params.dellist && !params.list_events &&
!params.show_lines))
usage_with_options(probe_usage, options);
@@ -246,7 +252,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)

if (params.nevents) {
ret = add_perf_probe_events(params.events, params.nevents,
- params.force_add);
+ params.force_add,
+ params.max_probe_points);
if (ret < 0) {
pr_err(" Error: Failed to add events. (%d)\n", ret);
return ret;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 5d3baec..9ded38c 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -150,7 +150,8 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,

/* Try to find perf_probe_event with debuginfo */
static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
- struct kprobe_trace_event **tevs)
+ struct kprobe_trace_event **tevs,
+ int max_tevs)
{
bool need_dwarf = perf_probe_event_need_dwarf(pev);
int fd, ntevs;
@@ -166,7 +167,7 @@ static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
}

/* Searching trace events corresponding to probe event */
- ntevs = find_kprobe_trace_events(fd, pev, tevs);
+ ntevs = find_kprobe_trace_events(fd, pev, tevs, max_tevs);
close(fd);

if (ntevs > 0) { /* Succeeded to find trace events */
@@ -318,7 +319,8 @@ static int convert_to_perf_probe_point(struct kprobe_trace_point *tp,
}

static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev,
- struct kprobe_trace_event **tevs __unused)
+ struct kprobe_trace_event **tevs __unused,
+ int max_tevs __unused)
{
if (perf_probe_event_need_dwarf(pev)) {
pr_warning("Debuginfo-analysis is not supported.\n");
@@ -1408,14 +1410,15 @@ static int __add_kprobe_trace_events(struct perf_probe_event *pev,
}

static int convert_to_kprobe_trace_events(struct perf_probe_event *pev,
- struct kprobe_trace_event **tevs)
+ struct kprobe_trace_event **tevs,
+ int max_tevs)
{
struct symbol *sym;
int ret = 0, i;
struct kprobe_trace_event *tev;

/* Convert perf_probe_event with debuginfo */
- ret = try_to_find_kprobe_trace_events(pev, tevs);
+ ret = try_to_find_kprobe_trace_events(pev, tevs, max_tevs);
if (ret != 0)
return ret;

@@ -1487,7 +1490,7 @@ struct __event_package {
};

int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
- bool force_add)
+ bool force_add, int max_tevs)
{
int i, j, ret;
struct __event_package *pkgs;
@@ -1506,7 +1509,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_kprobe_trace_events(pkgs[i].pev,
- &pkgs[i].tevs);
+ &pkgs[i].tevs, 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 e7ff0d0..e9db1a2 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -115,8 +115,8 @@ extern void clear_kprobe_trace_event(struct kprobe_trace_event *tev);
extern int parse_line_range_desc(const char *cmd, struct line_range *lr);


-extern int add_perf_probe_events(struct perf_probe_event *pevs, int ntevs,
- bool force_add);
+extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
+ bool force_add, int max_probe_points);
extern int del_perf_probe_events(struct strlist *dellist);
extern int show_perf_probe_events(void);
extern int show_line_range(struct line_range *lr);
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 0d795bc..562b144 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -626,8 +626,9 @@ static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf)
Dwarf_Attribute fb_attr;
size_t nops;

- if (pf->ntevs == MAX_PROBES) {
- pr_warning("Too many( > %d) probe point found.\n", MAX_PROBES);
+ if (pf->ntevs == pf->max_tevs) {
+ pr_warning("Too many( > %d) probe point found.\n",
+ pf->max_tevs);
return -ERANGE;
}
tev = &pf->tevs[pf->ntevs++];
@@ -932,9 +933,9 @@ static int find_probe_point_by_func(struct probe_finder *pf)

/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
- struct kprobe_trace_event **tevs)
+ struct kprobe_trace_event **tevs, int max_tevs)
{
- struct probe_finder pf = {.pev = pev};
+ struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs};
struct perf_probe_point *pp = &pev->point;
Dwarf_Off off, noff;
size_t cuhl;
@@ -942,7 +943,7 @@ int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
Dwarf *dbg;
int ret = 0;

- pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * MAX_PROBES);
+ pf.tevs = zalloc(sizeof(struct kprobe_trace_event) * max_tevs);
if (pf.tevs == NULL)
return -ENOMEM;
*tevs = pf.tevs;
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 310ce89..66f1980 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -18,7 +18,8 @@ static inline int is_c_varname(const char *name)
#ifdef DWARF_SUPPORT
/* Find kprobe_trace_events specified by perf_probe_event from debuginfo */
extern int find_kprobe_trace_events(int fd, struct perf_probe_event *pev,
- struct kprobe_trace_event **tevs);
+ struct kprobe_trace_event **tevs,
+ int max_tevs);

/* Find a perf_probe_point from debuginfo */
extern int find_perf_probe_point(int fd, unsigned long addr,
@@ -32,7 +33,8 @@ extern int find_line_range(int fd, struct line_range *lr);
struct probe_finder {
struct perf_probe_event *pev; /* Target probe event */
struct kprobe_trace_event *tevs; /* Result trace events */
- int ntevs; /* number of trace events */
+ int ntevs; /* Number of trace events */
+ int max_tevs; /* Max number of trace events */

/* For function searching */
int lno; /* Line number */

2010-04-27 12:59:44

by Masami Hiramatsu

[permalink] [raw]
Subject: [tip:perf/core] perf probe: Fix to exit callback soon after finding too many probe points

Commit-ID: 5d1ee0413c8e2e0aa48510b1edfb3c4d2d43455b
Gitweb: http://git.kernel.org/tip/5d1ee0413c8e2e0aa48510b1edfb3c4d2d43455b
Author: Masami Hiramatsu <[email protected]>
AuthorDate: Wed, 21 Apr 2010 15:56:32 -0400
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Mon, 26 Apr 2010 15:33:08 -0300

perf probe: Fix to exit callback soon after finding too many probe points

Fix to exit callback soon after finding too many probe points.
Don't try to continue searching because it already failed.

Signed-off-by: Masami Hiramatsu <[email protected]>
Reported-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/probe-finder.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index e7ee52f..0d795bc 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -871,6 +871,8 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
(uintmax_t)pf->addr);

param->retval = convert_probe_point(in_die, pf);
+ if (param->retval < 0)
+ return DWARF_CB_ABORT;
}

return DWARF_CB_OK;
@@ -1106,6 +1108,8 @@ static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data)
return DWARF_CB_OK;

param->retval = line_range_add_line(src, lineno, lf->lr);
+ if (param->retval < 0)
+ return DWARF_CB_ABORT;
return DWARF_CB_OK;
}