2 * probe-file.c : operate ftrace k/uprobe events files
4 * Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.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.
25 #include <api/fs/debugfs.h>
26 #include <api/fs/tracefs.h>
27 #include "probe-event.h"
28 #include "probe-file.h"
31 #define MAX_CMDLEN 256
33 static void print_open_warning(int err
, bool uprobe
)
35 char sbuf
[STRERR_BUFSIZE
];
41 config
= "CONFIG_UPROBE_EVENTS";
43 config
= "CONFIG_KPROBE_EVENTS";
45 pr_warning("%cprobe_events file does not exist"
46 " - please rebuild kernel with %s.\n",
47 uprobe
? 'u' : 'k', config
);
48 } else if (err
== -ENOTSUP
)
49 pr_warning("Tracefs or debugfs is not mounted.\n");
51 pr_warning("Failed to open %cprobe_events: %s\n",
53 strerror_r(-err
, sbuf
, sizeof(sbuf
)));
56 static void print_both_open_warning(int kerr
, int uerr
)
58 /* Both kprobes and uprobes are disabled, warn it. */
59 if (kerr
== -ENOTSUP
&& uerr
== -ENOTSUP
)
60 pr_warning("Tracefs or debugfs is not mounted.\n");
61 else if (kerr
== -ENOENT
&& uerr
== -ENOENT
)
62 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
63 "or/and CONFIG_UPROBE_EVENTS.\n");
65 char sbuf
[STRERR_BUFSIZE
];
66 pr_warning("Failed to open kprobe events: %s.\n",
67 strerror_r(-kerr
, sbuf
, sizeof(sbuf
)));
68 pr_warning("Failed to open uprobe events: %s.\n",
69 strerror_r(-uerr
, sbuf
, sizeof(sbuf
)));
73 static int open_probe_events(const char *trace_file
, bool readwrite
)
76 const char *__debugfs
;
77 const char *tracing_dir
= "";
80 __debugfs
= tracefs_find_mountpoint();
81 if (__debugfs
== NULL
) {
82 tracing_dir
= "tracing/";
84 __debugfs
= debugfs_find_mountpoint();
85 if (__debugfs
== NULL
)
89 ret
= e_snprintf(buf
, PATH_MAX
, "%s/%s%s",
90 __debugfs
, tracing_dir
, trace_file
);
92 pr_debug("Opening %s write=%d\n", buf
, readwrite
);
93 if (readwrite
&& !probe_event_dry_run
)
94 ret
= open(buf
, O_RDWR
| O_APPEND
, 0);
96 ret
= open(buf
, O_RDONLY
, 0);
104 static int open_kprobe_events(bool readwrite
)
106 return open_probe_events("kprobe_events", readwrite
);
109 static int open_uprobe_events(bool readwrite
)
111 return open_probe_events("uprobe_events", readwrite
);
114 int probe_file__open(int flag
)
118 if (flag
& PF_FL_UPROBE
)
119 fd
= open_uprobe_events(flag
& PF_FL_RW
);
121 fd
= open_kprobe_events(flag
& PF_FL_RW
);
123 print_open_warning(fd
, flag
& PF_FL_UPROBE
);
128 int probe_file__open_both(int *kfd
, int *ufd
, int flag
)
133 *kfd
= open_kprobe_events(flag
& PF_FL_RW
);
134 *ufd
= open_uprobe_events(flag
& PF_FL_RW
);
135 if (*kfd
< 0 && *ufd
< 0) {
136 print_both_open_warning(*kfd
, *ufd
);
143 /* Get raw string list of current kprobe_events or uprobe_events */
144 struct strlist
*probe_file__get_rawlist(int fd
)
148 char buf
[MAX_CMDLEN
];
152 sl
= strlist__new(NULL
, NULL
);
154 fp
= fdopen(dup(fd
), "r");
156 p
= fgets(buf
, MAX_CMDLEN
, fp
);
163 ret
= strlist__add(sl
, buf
);
165 pr_debug("strlist__add failed (%d)\n", ret
);
175 static struct strlist
*__probe_file__get_namelist(int fd
, bool include_group
)
178 struct strlist
*sl
, *rawlist
;
179 struct str_node
*ent
;
180 struct probe_trace_event tev
;
183 memset(&tev
, 0, sizeof(tev
));
184 rawlist
= probe_file__get_rawlist(fd
);
187 sl
= strlist__new(NULL
, NULL
);
188 strlist__for_each(ent
, rawlist
) {
189 ret
= parse_probe_trace_command(ent
->s
, &tev
);
193 ret
= e_snprintf(buf
, 128, "%s:%s", tev
.group
,
196 ret
= strlist__add(sl
, buf
);
198 ret
= strlist__add(sl
, tev
.event
);
199 clear_probe_trace_event(&tev
);
203 strlist__delete(rawlist
);
212 /* Get current perf-probe event names */
213 struct strlist
*probe_file__get_namelist(int fd
)
215 return __probe_file__get_namelist(fd
, false);
218 int probe_file__add_event(int fd
, struct probe_trace_event
*tev
)
221 char *buf
= synthesize_probe_trace_command(tev
);
222 char sbuf
[STRERR_BUFSIZE
];
225 pr_debug("Failed to synthesize probe trace event.\n");
229 pr_debug("Writing event: %s\n", buf
);
230 if (!probe_event_dry_run
) {
231 ret
= write(fd
, buf
, strlen(buf
));
234 pr_warning("Failed to write event: %s\n",
235 strerror_r(errno
, sbuf
, sizeof(sbuf
)));
243 static int __del_trace_probe_event(int fd
, struct str_node
*ent
)
249 /* Convert from perf-probe event to trace-probe event */
250 ret
= e_snprintf(buf
, 128, "-:%s", ent
->s
);
254 p
= strchr(buf
+ 2, ':');
256 pr_debug("Internal error: %s should have ':' but not.\n",
263 pr_debug("Writing event: %s\n", buf
);
264 ret
= write(fd
, buf
, strlen(buf
));
270 pr_info("Removed event: %s\n", ent
->s
);
273 pr_warning("Failed to delete event: %s\n",
274 strerror_r(-ret
, buf
, sizeof(buf
)));
278 int probe_file__del_events(int fd
, struct strfilter
*filter
)
280 struct strlist
*namelist
;
281 struct str_node
*ent
;
285 namelist
= __probe_file__get_namelist(fd
, true);
289 strlist__for_each(ent
, namelist
) {
290 p
= strchr(ent
->s
, ':');
291 if ((p
&& strfilter__compare(filter
, p
+ 1)) ||
292 strfilter__compare(filter
, ent
->s
)) {
293 ret
= __del_trace_probe_event(fd
, ent
);
298 strlist__delete(namelist
);