perf probe: Support event name for --add option
authorMasami Hiramatsu <mhiramat@redhat.com>
Tue, 15 Dec 2009 15:32:18 +0000 (10:32 -0500)
committerIngo Molnar <mingo@elte.hu>
Tue, 15 Dec 2009 19:22:03 +0000 (20:22 +0100)
Support event name syntax for --add option. This allows
users to specify event name for each new event.

The --add syntax is:
 perf probe --add '[EVENT=]SRC:LINE ARGS'
or
 perf probe --add '[EVENT=]FUNC[+OFFS|%return|:RLN][@SRC] ARGS'

e.g.

 ./perf probe --add myprobe1=schedule

Note: currently group name is not supported yet, because it
can cause name-space confliction with other tracepoint/
hw-breakpoint events.

Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Jim Keniston <jkenisto@us.ibm.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Frank Ch. Eigler <fche@redhat.com>
Cc: Jason Baron <jbaron@redhat.com>
Cc: K.Prasad <prasad@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Cc: systemtap <systemtap@sources.redhat.com>
Cc: DLE <dle-develop@lists.sourceforge.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <20091215153218.17436.84675.stgit@dhcp-100-2-132.bos.redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
tools/perf/Documentation/perf-probe.txt
tools/perf/builtin-probe.c
tools/perf/util/probe-event.c
tools/perf/util/probe-event.h
tools/perf/util/probe-finder.h

index 8fa6bf99fcb570c334424627df4021671e2e1d97..250e391b4bc838691f13e4c407193935ccfb83e8 100644 (file)
@@ -49,8 +49,9 @@ PROBE SYNTAX
 ------------
 Probe points are defined by following syntax.
 
- "FUNC[+OFFS|:RLN|%return][@SRC]|SRC:ALN [ARG ...]"
+ "[EVENT=]FUNC[+OFFS|:RLN|%return][@SRC]|SRC:ALN [ARG ...]"
 
+'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'.
 'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, 'RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. In addition, 'SRC' specifies a source file which has that function.
 It is also possible to specify a probe point by the source line number by using 'SRC:ALN' syntax, where 'SRC' is the source file path and 'ALN' is the line number.
 'ARG' specifies the arguments of this probe point. You can use the name of local variable, or kprobe-tracer argument format (e.g. $retval, %ax, etc).
index 438a7bb101d3b75498eb184a114be7e4747cdd16..adc0a55acd95319691dd46c8cfce55c00cd58929 100644 (file)
@@ -172,13 +172,13 @@ static const struct option options[] = {
                opt_del_probe_event),
        OPT_CALLBACK('a', "add", NULL,
 #ifdef NO_LIBDWARF
-               "FUNC[+OFFS|%return] [ARG ...]",
+               "[EVENT=]FUNC[+OFFS|%return] [ARG ...]",
 #else
-               "FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]",
+               "[EVENT=]FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]",
 #endif
                "probe point definition, where\n"
-               "\t\tGRP:\tGroup name (optional)\n"
-               "\t\tNAME:\tEvent name\n"
+               "\t\tGROUP:\tGroup name (optional)\n"
+               "\t\tEVENT:\tEvent name\n"
                "\t\tFUNC:\tFunction name\n"
                "\t\tOFFS:\tOffset from function entry (in byte)\n"
                "\t\t%return:\tPut the probe at function return\n"
index 5e99e52b0179977a0a592cab3e0f8e6ae6282d0f..3b4cf456165c7d35b6096b5d756989cf9174d508 100644 (file)
@@ -69,10 +69,23 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp)
        char c, nc = 0;
        /*
         * <Syntax>
-        * perf probe SRC:LN
-        * perf probe FUNC[+OFFS|%return][@SRC]
+        * perf probe [EVENT=]SRC:LN
+        * perf probe [EVENT=]FUNC[+OFFS|%return][@SRC]
+        *
+        * TODO:Group name support
         */
 
+       ptr = strchr(arg, '=');
+       if (ptr) {      /* Event name */
+               *ptr = '\0';
+               tmp = ptr + 1;
+               ptr = strchr(arg, ':');
+               if (ptr)        /* Group name is not supported yet. */
+                       semantic_error("Group name is not supported yet.");
+               pp->event = strdup(arg);
+               arg = tmp;
+       }
+
        ptr = strpbrk(arg, ":+@%");
        if (ptr) {
                nc = *ptr;
@@ -188,8 +201,7 @@ void parse_perf_probe_event(const char *str, struct probe_point *pp,
 }
 
 /* Parse kprobe_events event into struct probe_point */
-void parse_trace_kprobe_event(const char *str, char **group, char **event,
-                             struct probe_point *pp)
+void parse_trace_kprobe_event(const char *str, struct probe_point *pp)
 {
        char pr;
        char *p;
@@ -205,18 +217,17 @@ void parse_trace_kprobe_event(const char *str, char **group, char **event,
 
        /* Scan event and group name. */
        ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]",
-                    &pr, (float *)(void *)group, (float *)(void *)event);
+                    &pr, (float *)(void *)&pp->group,
+                    (float *)(void *)&pp->event);
        if (ret != 3)
                semantic_error("Failed to parse event name: %s", argv[0]);
-       pr_debug("Group:%s Event:%s probe:%c\n", *group, *event, pr);
-
-       if (!pp)
-               goto end;
+       pr_debug("Group:%s Event:%s probe:%c\n", pp->group, pp->event, pr);
 
        pp->retprobe = (pr == 'r');
 
        /* Scan function name and offset */
-       ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function, &pp->offset);
+       ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function,
+                    &pp->offset);
        if (ret == 1)
                pp->offset = 0;
 
@@ -235,7 +246,6 @@ void parse_trace_kprobe_event(const char *str, char **group, char **event,
                        die("Failed to copy argument.");
        }
 
-end:
        argv_free(argv);
 }
 
@@ -368,6 +378,10 @@ static void clear_probe_point(struct probe_point *pp)
 {
        int i;
 
+       if (pp->event)
+               free(pp->event);
+       if (pp->group)
+               free(pp->group);
        if (pp->function)
                free(pp->function);
        if (pp->file)
@@ -382,13 +396,13 @@ static void clear_probe_point(struct probe_point *pp)
 }
 
 /* Show an event */
-static void show_perf_probe_event(const char *group, const char *event,
-                                 const char *place, struct probe_point *pp)
+static void show_perf_probe_event(const char *event, const char *place,
+                                 struct probe_point *pp)
 {
        int i, ret;
        char buf[128];
 
-       ret = e_snprintf(buf, 128, "%s:%s", group, event);
+       ret = e_snprintf(buf, 128, "%s:%s", pp->group, event);
        if (ret < 0)
                die("Failed to copy event: %s", strerror(-ret));
        printf("  %-40s (on %s", buf, place);
@@ -405,7 +419,6 @@ static void show_perf_probe_event(const char *group, const char *event,
 void show_perf_probe_events(void)
 {
        int fd, nr;
-       char *group, *event;
        struct probe_point pp;
        struct strlist *rawlist;
        struct str_node *ent;
@@ -415,16 +428,14 @@ void show_perf_probe_events(void)
        close(fd);
 
        strlist__for_each(ent, rawlist) {
-               parse_trace_kprobe_event(ent->s, &group, &event, &pp);
+               parse_trace_kprobe_event(ent->s, &pp);
                /* Synthesize only event probe point */
                nr = pp.nr_args;
                pp.nr_args = 0;
                synthesize_perf_probe_event(&pp);
                pp.nr_args = nr;
                /* Show an event */
-               show_perf_probe_event(group, event, pp.probes[0], &pp);
-               free(group);
-               free(event);
+               show_perf_probe_event(pp.event, pp.probes[0], &pp);
                clear_probe_point(&pp);
        }
 
@@ -434,24 +445,25 @@ void show_perf_probe_events(void)
 /* Get current perf-probe event names */
 static struct strlist *get_perf_event_names(int fd, bool include_group)
 {
-       char *group, *event;
        char buf[128];
        struct strlist *sl, *rawlist;
        struct str_node *ent;
+       struct probe_point pp;
 
+       memset(&pp, 0, sizeof(pp));
        rawlist = get_trace_kprobe_event_rawlist(fd);
 
        sl = strlist__new(true, NULL);
        strlist__for_each(ent, rawlist) {
-               parse_trace_kprobe_event(ent->s, &group, &event, NULL);
+               parse_trace_kprobe_event(ent->s, &pp);
                if (include_group) {
-                       if (e_snprintf(buf, 128, "%s:%s", group, event) < 0)
+                       if (e_snprintf(buf, 128, "%s:%s", pp.group,
+                                      pp.event) < 0)
                                die("Failed to copy group:event name.");
                        strlist__add(sl, buf);
                } else
-                       strlist__add(sl, event);
-               free(group);
-               free(event);
+                       strlist__add(sl, pp.event);
+               clear_probe_point(&pp);
        }
 
        strlist__delete(rawlist);
@@ -507,19 +519,23 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes)
 
        for (j = 0; j < nr_probes; j++) {
                pp = probes + j;
+               if (!pp->event)
+                       pp->event = strdup(pp->function);
+               if (!pp->group)
+                       pp->group = strdup(PERFPROBE_GROUP);
+               DIE_IF(!pp->event || !pp->group);
                for (i = 0; i < pp->found; i++) {
                        /* Get an unused new event name */
-                       get_new_event_name(event, 64, pp->function, namelist);
+                       get_new_event_name(event, 64, pp->event, namelist);
                        snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s\n",
                                 pp->retprobe ? 'r' : 'p',
-                                PERFPROBE_GROUP, event,
+                                pp->group, event,
                                 pp->probes[i]);
                        write_trace_kprobe_event(fd, buf);
                        printf("Added new event:\n");
                        /* Get the first parameter (probe-point) */
                        sscanf(pp->probes[i], "%s", buf);
-                       show_perf_probe_event(PERFPROBE_GROUP, event,
-                                             buf, pp);
+                       show_perf_probe_event(event, buf, pp);
                        /* Add added event name to namelist */
                        strlist__add(namelist, event);
                }
index 028575b5fc3bb9681094eeaa5a61a2500e6b7646..8bb22f5246ccf72fbb41fa5739f631f367846300 100644 (file)
@@ -8,8 +8,7 @@
 extern void parse_perf_probe_event(const char *str, struct probe_point *pp,
                                   bool *need_dwarf);
 extern int synthesize_perf_probe_event(struct probe_point *pp);
-extern void parse_trace_kprobe_event(const char *str, char **group,
-                                    char **event, struct probe_point *pp);
+extern void parse_trace_kprobe_event(const char *str, struct probe_point *pp);
 extern int synthesize_trace_kprobe_event(struct probe_point *pp);
 extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes);
 extern void del_trace_kprobe_events(struct strlist *dellist);
index bdebca6697d24a637f583295779f3c2697f8b319..5e4050ce296301bd75a083b5673dee2660d8ad38 100644 (file)
@@ -12,6 +12,9 @@ static inline int is_c_varname(const char *name)
 }
 
 struct probe_point {
+       char    *event;         /* Event name */
+       char    *group;         /* Event group */
+
        /* Inputs */
        char    *file;          /* File name */
        int     line;           /* Line number */