2 * probe-event.c : perf-probe definition to kprobe_events format converter
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include <sys/utsname.h>
24 #include <sys/types.h>
37 #include "parse-events.h" /* For debugfs_path */
38 #include "probe-event.h"
40 #define MAX_CMDLEN 256
41 #define MAX_PROBE_ARGS 128
42 #define PERFPROBE_GROUP "probe"
44 #define semantic_error(msg ...) die("Semantic error :" msg)
46 /* Parse probepoint definition. */
47 static void parse_perf_probe_probepoint(char *arg
, struct probe_point
*pp
)
54 * perf probe FUNC[+OFFS|%return][@SRC]
57 ptr
= strpbrk(arg
, ":+@%");
63 /* Check arg is function or file and copy it */
64 if (strchr(arg
, '.')) /* File */
65 pp
->file
= strdup(arg
);
67 pp
->function
= strdup(arg
);
68 DIE_IF(pp
->file
== NULL
&& pp
->function
== NULL
);
70 /* Parse other options */
74 ptr
= strpbrk(arg
, ":+@%");
80 case ':': /* Line number */
81 pp
->line
= strtoul(arg
, &tmp
, 0);
83 semantic_error("There is non-digit charactor"
86 case '+': /* Byte offset from a symbol */
87 pp
->offset
= strtoul(arg
, &tmp
, 0);
89 semantic_error("There is non-digit charactor"
92 case '@': /* File name */
94 semantic_error("SRC@SRC is not allowed.");
95 pp
->file
= strdup(arg
);
96 DIE_IF(pp
->file
== NULL
);
98 semantic_error("@SRC must be the last "
101 case '%': /* Probe places */
102 if (strcmp(arg
, "return") == 0) {
104 } else /* Others not supported yet */
105 semantic_error("%%%s is not supported.", arg
);
108 DIE_IF("Program has a bug.");
113 /* Exclusion check */
114 if (pp
->line
&& pp
->offset
)
115 semantic_error("Offset can't be used with line number.");
117 if (!pp
->line
&& pp
->file
&& !pp
->function
)
118 semantic_error("File always requires line number.");
120 if (pp
->offset
&& !pp
->function
)
121 semantic_error("Offset requires an entry function.");
123 if (pp
->retprobe
&& !pp
->function
)
124 semantic_error("Return probe requires an entry function.");
126 if ((pp
->offset
|| pp
->line
) && pp
->retprobe
)
127 semantic_error("Offset/Line can't be used with return probe.");
129 pr_debug("symbol:%s file:%s line:%d offset:%d, return:%d\n",
130 pp
->function
, pp
->file
, pp
->line
, pp
->offset
, pp
->retprobe
);
133 /* Parse perf-probe event definition */
134 int parse_perf_probe_event(const char *str
, struct probe_point
*pp
)
137 int argc
, i
, need_dwarf
= 0;
139 argv
= argv_split(str
, &argc
);
141 die("argv_split failed.");
142 if (argc
> MAX_PROBE_ARGS
+ 1)
143 semantic_error("Too many arguments");
145 /* Parse probe point */
146 parse_perf_probe_probepoint(argv
[0], pp
);
147 if (pp
->file
|| pp
->line
)
150 /* Copy arguments and ensure return probe has no C argument */
151 pp
->nr_args
= argc
- 1;
152 pp
->args
= zalloc(sizeof(char *) * pp
->nr_args
);
153 for (i
= 0; i
< pp
->nr_args
; i
++) {
154 pp
->args
[i
] = strdup(argv
[i
+ 1]);
156 die("Failed to copy argument.");
157 if (is_c_varname(pp
->args
[i
])) {
159 semantic_error("You can't specify local"
160 " variable for kretprobe");
169 int synthesize_trace_kprobe_event(struct probe_point
*pp
)
174 pp
->probes
[0] = buf
= zalloc(MAX_CMDLEN
);
176 die("Failed to allocate memory by zalloc.");
177 ret
= snprintf(buf
, MAX_CMDLEN
, "%s+%d", pp
->function
, pp
->offset
);
178 if (ret
<= 0 || ret
>= MAX_CMDLEN
)
182 for (i
= 0; i
< pp
->nr_args
; i
++) {
183 ret
= snprintf(&buf
[len
], MAX_CMDLEN
- len
, " %s",
185 if (ret
<= 0 || ret
>= MAX_CMDLEN
- len
)
200 static int write_trace_kprobe_event(int fd
, const char *buf
)
204 ret
= write(fd
, buf
, strlen(buf
));
206 die("Failed to create event.");
208 printf("Added new event: %s\n", buf
);
213 void add_trace_kprobe_events(struct probe_point
*probes
, int nr_probes
)
216 struct probe_point
*pp
;
217 char buf
[MAX_CMDLEN
];
219 snprintf(buf
, MAX_CMDLEN
, "%s/../kprobe_events", debugfs_path
);
220 fd
= open(buf
, O_WRONLY
, O_APPEND
);
223 die("kprobe_events file does not exist -"
224 " please rebuild with CONFIG_KPROBE_TRACER.");
226 die("Could not open kprobe_events file: %s",
230 for (j
= 0; j
< nr_probes
; j
++) {
232 if (pp
->found
== 1) {
233 snprintf(buf
, MAX_CMDLEN
, "%c:%s/%s_%x %s\n",
234 pp
->retprobe
? 'r' : 'p', PERFPROBE_GROUP
,
235 pp
->function
, pp
->offset
, pp
->probes
[0]);
236 write_trace_kprobe_event(fd
, buf
);
238 for (i
= 0; i
< pp
->found
; i
++) {
239 snprintf(buf
, MAX_CMDLEN
, "%c:%s/%s_%x_%d %s\n",
240 pp
->retprobe
? 'r' : 'p',
242 pp
->function
, pp
->offset
, i
,
244 write_trace_kprobe_event(fd
, buf
);