Merge branch 'perf' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2...
authorIngo Molnar <mingo@elte.hu>
Tue, 27 Apr 2010 09:16:54 +0000 (11:16 +0200)
committerIngo Molnar <mingo@elte.hu>
Tue, 27 Apr 2010 09:16:54 +0000 (11:16 +0200)
tools/perf/Documentation/perf-probe.txt
tools/perf/Makefile
tools/perf/builtin-probe.c
tools/perf/util/probe-event.c
tools/perf/util/probe-event.h
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h
tools/perf/util/symbol.c

index 63c25d3048803bb5fcc2796ba02365c41aa80581..94a258c96a440b091616264fb2a7d0fd8b515967 100644 (file)
@@ -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.
index e8bf2e1ab4976762c3e5b702bd68a54b29317de5..3ac6b677becd78e134121bf109f28078a8fad9ec 100644 (file)
@@ -504,7 +504,7 @@ PERFLIBS = $(LIB_FILE)
 
 ifndef NO_DWARF
 ifneq ($(shell sh -c "(echo '\#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
-       msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev);
+       msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/libdw-dev);
        NO_DWARF := 1
 endif # Dwarf support
 endif # NO_DWARF
index c1e54035e8cfc99cd18f7878d4488f9523bbb5df..61c6d70732c9888dac776a07731e892723addfbb 100644 (file)
@@ -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;
index 4fb480367c3ec5e861827a2645f941f8ef595f2d..9ded38ced23489805db36834114ff08aca2697d3 100644 (file)
@@ -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 */
@@ -180,15 +181,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
@@ -317,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");
@@ -1407,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;
 
@@ -1486,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;
@@ -1505,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;
index e7ff0d02c0d484d4557fece861196c98e4bc309a..e9db1a214ca4d9c4c7f9e3a46151070c6cd68ce7 100644 (file)
@@ -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);
index e7ee52fd0e090d6e1e6b3a3dcbcb4f16cd2636d6..562b1443e785358c7c72a2fd55df0e76332a7d96 100644 (file)
@@ -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++];
@@ -871,6 +872,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;
@@ -930,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;
@@ -940,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;
@@ -1106,6 +1109,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;
 }
 
index 310ce897229cc30302b3edf1f426ee57fd066e6b..66f1980e3855477c86602485e43803b98b0032a8 100644 (file)
@@ -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 */
index e782e7db16c5310ae19365d07bb241ae31b1c61d..e77c33a11de3b88f088c3ac390a3cdea194492ad 100644 (file)
@@ -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;