Skip to content

Commit

Permalink
perf probe: Support event name for --add option
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Arnaldo Carvalho de Melo <[email protected]>
Cc: Steven Rostedt <[email protected]>
Cc: Jim Keniston <[email protected]>
Cc: Ananth N Mavinakayanahalli <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Cc: Frank Ch. Eigler <[email protected]>
Cc: Jason Baron <[email protected]>
Cc: K.Prasad <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Srikar Dronamraju <[email protected]>
Cc: systemtap <[email protected]>
Cc: DLE <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
  • Loading branch information
Masami Hiramatsu authored and Ingo Molnar committed Dec 15, 2009
1 parent bbbb521 commit af663d7
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 36 deletions.
3 changes: 2 additions & 1 deletion tools/perf/Documentation/perf-probe.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
8 changes: 4 additions & 4 deletions tools/perf/builtin-probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
74 changes: 45 additions & 29 deletions tools/perf/util/probe-event.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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);
}

Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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);
}

Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down
3 changes: 1 addition & 2 deletions tools/perf/util/probe-event.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions tools/perf/util/probe-finder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit af663d7

Please sign in to comment.