blob: 405b5b0f903e9b6ec192ab5acd3b893dbabbaa94 [file] [log] [blame]
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001/*
Masami Hiramatsu77b44d12009-11-03 19:12:47 -05002 * Kprobes-based tracing events
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04003 *
4 * Created by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/module.h>
21#include <linux/uaccess.h>
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040022
Srikar Dronamraju8ab83f52012-04-09 14:41:44 +053023#include "trace_probe.h"
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040024
Masami Hiramatsuf52487e2009-09-10 19:53:53 -040025#define KPROBE_EVENT_SYSTEM "kprobes"
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040026
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040027/**
Masami Hiramatsu77b44d12009-11-03 19:12:47 -050028 * Kprobe event core functions
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040029 */
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040030struct trace_probe {
31 struct list_head list;
Masami Hiramatsu4a846b42009-09-11 05:31:21 +020032 struct kretprobe rp; /* Use rp.kp for kprobe use */
Masami Hiramatsucd7e7bd2009-08-13 16:35:42 -040033 unsigned long nhit;
Masami Hiramatsu50d78052009-09-14 16:49:20 -040034 unsigned int flags; /* For TP_FLAG_* */
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040035 const char *symbol; /* symbol name */
Steven Rostedt22392912010-04-21 12:27:06 -040036 struct ftrace_event_class class;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040037 struct ftrace_event_call call;
Oleg Nesterovb04d52e2013-06-20 19:38:14 +020038 struct list_head files;
Masami Hiramatsu93ccae72010-04-12 13:17:08 -040039 ssize_t size; /* trace entry size */
Masami Hiramatsua82378d2009-08-13 16:35:18 -040040 unsigned int nr_args;
Masami Hiramatsueca0d912009-09-10 19:53:38 -040041 struct probe_arg args[];
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040042};
43
Oleg Nesterovb04d52e2013-06-20 19:38:14 +020044struct event_file_link {
45 struct ftrace_event_file *file;
46 struct list_head list;
47};
48
Masami Hiramatsua82378d2009-08-13 16:35:18 -040049#define SIZEOF_TRACE_PROBE(n) \
50 (offsetof(struct trace_probe, args) + \
Masami Hiramatsueca0d912009-09-10 19:53:38 -040051 (sizeof(struct probe_arg) * (n)))
Masami Hiramatsua82378d2009-08-13 16:35:18 -040052
Masami Hiramatsu93ccae72010-04-12 13:17:08 -040053
Masami Hiramatsudb020382013-05-09 14:44:32 +090054static __kprobes bool trace_probe_is_return(struct trace_probe *tp)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040055{
Masami Hiramatsu4a846b42009-09-11 05:31:21 +020056 return tp->rp.handler != NULL;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040057}
58
Masami Hiramatsu7143f162011-06-27 16:26:36 +090059static __kprobes const char *trace_probe_symbol(struct trace_probe *tp)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040060{
61 return tp->symbol ? tp->symbol : "unknown";
62}
63
Masami Hiramatsu61424312011-06-27 16:26:56 +090064static __kprobes unsigned long trace_probe_offset(struct trace_probe *tp)
65{
66 return tp->rp.kp.offset;
67}
68
69static __kprobes bool trace_probe_is_enabled(struct trace_probe *tp)
70{
71 return !!(tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE));
72}
73
74static __kprobes bool trace_probe_is_registered(struct trace_probe *tp)
75{
76 return !!(tp->flags & TP_FLAG_REGISTERED);
77}
78
79static __kprobes bool trace_probe_has_gone(struct trace_probe *tp)
80{
81 return !!(kprobe_gone(&tp->rp.kp));
82}
83
84static __kprobes bool trace_probe_within_module(struct trace_probe *tp,
85 struct module *mod)
86{
87 int len = strlen(mod->name);
88 const char *name = trace_probe_symbol(tp);
89 return strncmp(mod->name, name, len) == 0 && name[len] == ':';
90}
91
92static __kprobes bool trace_probe_is_on_module(struct trace_probe *tp)
93{
94 return !!strchr(trace_probe_symbol(tp), ':');
95}
96
Masami Hiramatsu413d37d2009-08-13 16:35:11 -040097static int register_probe_event(struct trace_probe *tp);
98static void unregister_probe_event(struct trace_probe *tp);
99
100static DEFINE_MUTEX(probe_lock);
101static LIST_HEAD(probe_list);
102
Masami Hiramatsu50d78052009-09-14 16:49:20 -0400103static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs);
104static int kretprobe_dispatcher(struct kretprobe_instance *ri,
105 struct pt_regs *regs);
106
Masami Hiramatsu4a846b42009-09-11 05:31:21 +0200107/*
108 * Allocate new trace_probe and initialize it (including kprobes).
109 */
Masami Hiramatsuf52487e2009-09-10 19:53:53 -0400110static struct trace_probe *alloc_trace_probe(const char *group,
111 const char *event,
Masami Hiramatsu4a846b42009-09-11 05:31:21 +0200112 void *addr,
113 const char *symbol,
114 unsigned long offs,
Srikar Dronamraju3a6b7662012-04-09 14:41:33 +0530115 int nargs, bool is_return)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400116{
117 struct trace_probe *tp;
Masami Hiramatsu6f3cf442009-12-16 17:24:08 -0500118 int ret = -ENOMEM;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400119
Masami Hiramatsua82378d2009-08-13 16:35:18 -0400120 tp = kzalloc(SIZEOF_TRACE_PROBE(nargs), GFP_KERNEL);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400121 if (!tp)
Masami Hiramatsu6f3cf442009-12-16 17:24:08 -0500122 return ERR_PTR(ret);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400123
124 if (symbol) {
125 tp->symbol = kstrdup(symbol, GFP_KERNEL);
126 if (!tp->symbol)
127 goto error;
Masami Hiramatsu4a846b42009-09-11 05:31:21 +0200128 tp->rp.kp.symbol_name = tp->symbol;
129 tp->rp.kp.offset = offs;
130 } else
131 tp->rp.kp.addr = addr;
132
133 if (is_return)
Masami Hiramatsu50d78052009-09-14 16:49:20 -0400134 tp->rp.handler = kretprobe_dispatcher;
Masami Hiramatsu4a846b42009-09-11 05:31:21 +0200135 else
Masami Hiramatsu50d78052009-09-14 16:49:20 -0400136 tp->rp.kp.pre_handler = kprobe_dispatcher;
Masami Hiramatsu4a846b42009-09-11 05:31:21 +0200137
Masami Hiramatsuda346342010-08-27 20:39:12 +0900138 if (!event || !is_good_name(event)) {
Masami Hiramatsu6f3cf442009-12-16 17:24:08 -0500139 ret = -EINVAL;
Masami Hiramatsu42635652009-08-13 16:35:26 -0400140 goto error;
Masami Hiramatsu6f3cf442009-12-16 17:24:08 -0500141 }
142
Steven Rostedt22392912010-04-21 12:27:06 -0400143 tp->call.class = &tp->class;
Masami Hiramatsu42635652009-08-13 16:35:26 -0400144 tp->call.name = kstrdup(event, GFP_KERNEL);
145 if (!tp->call.name)
146 goto error;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400147
Masami Hiramatsuda346342010-08-27 20:39:12 +0900148 if (!group || !is_good_name(group)) {
Masami Hiramatsu6f3cf442009-12-16 17:24:08 -0500149 ret = -EINVAL;
Masami Hiramatsuf52487e2009-09-10 19:53:53 -0400150 goto error;
Masami Hiramatsu6f3cf442009-12-16 17:24:08 -0500151 }
152
Steven Rostedt22392912010-04-21 12:27:06 -0400153 tp->class.system = kstrdup(group, GFP_KERNEL);
154 if (!tp->class.system)
Masami Hiramatsuf52487e2009-09-10 19:53:53 -0400155 goto error;
156
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400157 INIT_LIST_HEAD(&tp->list);
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200158 INIT_LIST_HEAD(&tp->files);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400159 return tp;
160error:
Masami Hiramatsuf52487e2009-09-10 19:53:53 -0400161 kfree(tp->call.name);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400162 kfree(tp->symbol);
163 kfree(tp);
Masami Hiramatsu6f3cf442009-12-16 17:24:08 -0500164 return ERR_PTR(ret);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400165}
166
167static void free_trace_probe(struct trace_probe *tp)
168{
169 int i;
170
171 for (i = 0; i < tp->nr_args; i++)
Srikar Dronamraju8ab83f52012-04-09 14:41:44 +0530172 traceprobe_free_probe_arg(&tp->args[i]);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400173
Steven Rostedt8f082012010-04-20 10:47:33 -0400174 kfree(tp->call.class->system);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400175 kfree(tp->call.name);
176 kfree(tp->symbol);
177 kfree(tp);
178}
179
Masami Hiramatsu7143f162011-06-27 16:26:36 +0900180static struct trace_probe *find_trace_probe(const char *event,
Masami Hiramatsudd004c42009-10-27 16:42:44 -0400181 const char *group)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400182{
183 struct trace_probe *tp;
184
185 list_for_each_entry(tp, &probe_list, list)
Masami Hiramatsudd004c42009-10-27 16:42:44 -0400186 if (strcmp(tp->call.name, event) == 0 &&
Steven Rostedt8f082012010-04-20 10:47:33 -0400187 strcmp(tp->call.class->system, group) == 0)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400188 return tp;
189 return NULL;
190}
191
Oleg Nesterov3fe3d612013-06-20 19:38:09 +0200192/*
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900193 * Enable trace_probe
194 * if the file is NULL, enable "perf" handler, or enable "trace" handler.
195 */
196static int
197enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
Masami Hiramatsu1538f882011-06-27 16:26:44 +0900198{
199 int ret = 0;
200
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900201 if (file) {
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200202 struct event_file_link *link;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900203
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200204 link = kmalloc(sizeof(*link), GFP_KERNEL);
205 if (!link) {
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900206 ret = -ENOMEM;
Oleg Nesterov3fe3d612013-06-20 19:38:09 +0200207 goto out;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900208 }
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900209
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200210 link->file = file;
211 list_add_tail_rcu(&link->list, &tp->files);
212
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900213 tp->flags |= TP_FLAG_TRACE;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900214 } else
215 tp->flags |= TP_FLAG_PROFILE;
216
zhangwei(Jovi)195a84d2013-06-14 10:10:38 +0800217 if (trace_probe_is_registered(tp) && !trace_probe_has_gone(tp)) {
Masami Hiramatsu1538f882011-06-27 16:26:44 +0900218 if (trace_probe_is_return(tp))
219 ret = enable_kretprobe(&tp->rp);
220 else
221 ret = enable_kprobe(&tp->rp.kp);
222 }
Oleg Nesterov3fe3d612013-06-20 19:38:09 +0200223 out:
Masami Hiramatsu1538f882011-06-27 16:26:44 +0900224 return ret;
225}
226
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200227static struct event_file_link *
228find_event_file_link(struct trace_probe *tp, struct ftrace_event_file *file)
Masami Hiramatsu1538f882011-06-27 16:26:44 +0900229{
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200230 struct event_file_link *link;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900231
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200232 list_for_each_entry(link, &tp->files, list)
233 if (link->file == file)
234 return link;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900235
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200236 return NULL;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900237}
238
239/*
240 * Disable trace_probe
241 * if the file is NULL, disable "perf" handler, or disable "trace" handler.
242 */
243static int
244disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
245{
246 int ret = 0;
247
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900248 if (file) {
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200249 struct event_file_link *link;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900250
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200251 link = find_event_file_link(tp, file);
252 if (!link) {
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900253 ret = -EINVAL;
Oleg Nesterov3fe3d612013-06-20 19:38:09 +0200254 goto out;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900255 }
256
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200257 list_del_rcu(&link->list);
258 /* synchronize with kprobe_trace_func/kretprobe_trace_func */
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900259 synchronize_sched();
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200260 kfree(link);
261
262 if (!list_empty(&tp->files))
263 goto out;
264
265 tp->flags &= ~TP_FLAG_TRACE;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900266 } else
267 tp->flags &= ~TP_FLAG_PROFILE;
268
Masami Hiramatsu61424312011-06-27 16:26:56 +0900269 if (!trace_probe_is_enabled(tp) && trace_probe_is_registered(tp)) {
Masami Hiramatsu1538f882011-06-27 16:26:44 +0900270 if (trace_probe_is_return(tp))
271 disable_kretprobe(&tp->rp);
272 else
273 disable_kprobe(&tp->rp.kp);
274 }
Oleg Nesterov3fe3d612013-06-20 19:38:09 +0200275 out:
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900276 return ret;
Masami Hiramatsu1538f882011-06-27 16:26:44 +0900277}
278
Masami Hiramatsu61424312011-06-27 16:26:56 +0900279/* Internal register function - just handle k*probes and flags */
280static int __register_trace_probe(struct trace_probe *tp)
281{
Masami Hiramatsu7f6878a2011-06-27 16:27:03 +0900282 int i, ret;
Masami Hiramatsu61424312011-06-27 16:26:56 +0900283
284 if (trace_probe_is_registered(tp))
285 return -EINVAL;
286
Masami Hiramatsu7f6878a2011-06-27 16:27:03 +0900287 for (i = 0; i < tp->nr_args; i++)
Srikar Dronamraju8ab83f52012-04-09 14:41:44 +0530288 traceprobe_update_arg(&tp->args[i]);
Masami Hiramatsu7f6878a2011-06-27 16:27:03 +0900289
Masami Hiramatsu61424312011-06-27 16:26:56 +0900290 /* Set/clear disabled flag according to tp->flag */
291 if (trace_probe_is_enabled(tp))
292 tp->rp.kp.flags &= ~KPROBE_FLAG_DISABLED;
293 else
294 tp->rp.kp.flags |= KPROBE_FLAG_DISABLED;
295
296 if (trace_probe_is_return(tp))
297 ret = register_kretprobe(&tp->rp);
298 else
299 ret = register_kprobe(&tp->rp.kp);
300
301 if (ret == 0)
302 tp->flags |= TP_FLAG_REGISTERED;
303 else {
304 pr_warning("Could not insert probe at %s+%lu: %d\n",
305 trace_probe_symbol(tp), trace_probe_offset(tp), ret);
306 if (ret == -ENOENT && trace_probe_is_on_module(tp)) {
307 pr_warning("This probe might be able to register after"
308 "target module is loaded. Continue.\n");
309 ret = 0;
310 } else if (ret == -EILSEQ) {
311 pr_warning("Probing address(0x%p) is not an "
312 "instruction boundary.\n",
313 tp->rp.kp.addr);
314 ret = -EINVAL;
315 }
316 }
317
318 return ret;
319}
320
321/* Internal unregister function - just handle k*probes and flags */
322static void __unregister_trace_probe(struct trace_probe *tp)
323{
324 if (trace_probe_is_registered(tp)) {
325 if (trace_probe_is_return(tp))
326 unregister_kretprobe(&tp->rp);
327 else
328 unregister_kprobe(&tp->rp.kp);
329 tp->flags &= ~TP_FLAG_REGISTERED;
330 /* Cleanup kprobe for reuse */
331 if (tp->rp.kp.symbol_name)
332 tp->rp.kp.addr = NULL;
333 }
334}
335
Masami Hiramatsu2d5e0672009-09-14 16:48:56 -0400336/* Unregister a trace_probe and probe_event: call with locking probe_lock */
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900337static int unregister_trace_probe(struct trace_probe *tp)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400338{
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900339 /* Enabled event can not be unregistered */
340 if (trace_probe_is_enabled(tp))
341 return -EBUSY;
342
Masami Hiramatsu61424312011-06-27 16:26:56 +0900343 __unregister_trace_probe(tp);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400344 list_del(&tp->list);
Masami Hiramatsu2d5e0672009-09-14 16:48:56 -0400345 unregister_probe_event(tp);
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900346
347 return 0;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400348}
349
350/* Register a trace_probe and probe_event */
351static int register_trace_probe(struct trace_probe *tp)
352{
353 struct trace_probe *old_tp;
354 int ret;
355
356 mutex_lock(&probe_lock);
357
Masami Hiramatsu61424312011-06-27 16:26:56 +0900358 /* Delete old (same name) event if exist */
Masami Hiramatsu7143f162011-06-27 16:26:36 +0900359 old_tp = find_trace_probe(tp->call.name, tp->call.class->system);
Masami Hiramatsu2d5e0672009-09-14 16:48:56 -0400360 if (old_tp) {
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900361 ret = unregister_trace_probe(old_tp);
362 if (ret < 0)
363 goto end;
Masami Hiramatsu2d5e0672009-09-14 16:48:56 -0400364 free_trace_probe(old_tp);
365 }
Masami Hiramatsu61424312011-06-27 16:26:56 +0900366
367 /* Register new event */
Masami Hiramatsu2d5e0672009-09-14 16:48:56 -0400368 ret = register_probe_event(tp);
369 if (ret) {
Paul Bolle426d3102010-08-07 12:30:03 +0200370 pr_warning("Failed to register probe event(%d)\n", ret);
Masami Hiramatsu2d5e0672009-09-14 16:48:56 -0400371 goto end;
372 }
373
Masami Hiramatsu61424312011-06-27 16:26:56 +0900374 /* Register k*probe */
375 ret = __register_trace_probe(tp);
376 if (ret < 0)
Masami Hiramatsu2d5e0672009-09-14 16:48:56 -0400377 unregister_probe_event(tp);
Masami Hiramatsu61424312011-06-27 16:26:56 +0900378 else
Masami Hiramatsu2d5e0672009-09-14 16:48:56 -0400379 list_add_tail(&tp->list, &probe_list);
Masami Hiramatsu61424312011-06-27 16:26:56 +0900380
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400381end:
382 mutex_unlock(&probe_lock);
383 return ret;
384}
385
Masami Hiramatsu61424312011-06-27 16:26:56 +0900386/* Module notifier call back, checking event on the module */
387static int trace_probe_module_callback(struct notifier_block *nb,
388 unsigned long val, void *data)
389{
390 struct module *mod = data;
391 struct trace_probe *tp;
392 int ret;
393
394 if (val != MODULE_STATE_COMING)
395 return NOTIFY_DONE;
396
397 /* Update probes on coming module */
398 mutex_lock(&probe_lock);
399 list_for_each_entry(tp, &probe_list, list) {
400 if (trace_probe_within_module(tp, mod)) {
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900401 /* Don't need to check busy - this should have gone. */
Masami Hiramatsu61424312011-06-27 16:26:56 +0900402 __unregister_trace_probe(tp);
403 ret = __register_trace_probe(tp);
404 if (ret)
405 pr_warning("Failed to re-register probe %s on"
406 "%s: %d\n",
407 tp->call.name, mod->name, ret);
408 }
409 }
410 mutex_unlock(&probe_lock);
411
412 return NOTIFY_DONE;
413}
414
415static struct notifier_block trace_probe_module_nb = {
416 .notifier_call = trace_probe_module_callback,
417 .priority = 1 /* Invoked after kprobe module callback */
418};
419
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400420static int create_trace_probe(int argc, char **argv)
421{
422 /*
423 * Argument syntax:
Masami Hiramatsu61424312011-06-27 16:26:56 +0900424 * - Add kprobe: p[:[GRP/]EVENT] [MOD:]KSYM[+OFFS]|KADDR [FETCHARGS]
425 * - Add kretprobe: r[:[GRP/]EVENT] [MOD:]KSYM[+0] [FETCHARGS]
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400426 * Fetch args:
Masami Hiramatsu2e06ff62009-10-07 18:27:59 -0400427 * $retval : fetch return value
428 * $stack : fetch stack address
429 * $stackN : fetch Nth of stack (N:0-)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400430 * @ADDR : fetch memory at ADDR (ADDR should be in kernel)
431 * @SYM[+|-offs] : fetch memory at SYM +|- offs (SYM is a data symbol)
432 * %REG : fetch register REG
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400433 * Dereferencing memory fetch:
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400434 * +|-offs(ARG) : fetch memory at ARG +|- offs address.
Masami Hiramatsueca0d912009-09-10 19:53:38 -0400435 * Alias name of args:
436 * NAME=FETCHARG : set NAME as alias of FETCHARG.
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400437 * Type of args:
438 * FETCHARG:TYPE : use TYPE instead of unsigned long.
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400439 */
440 struct trace_probe *tp;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400441 int i, ret = 0;
Srikar Dronamraju3a6b7662012-04-09 14:41:33 +0530442 bool is_return = false, is_delete = false;
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400443 char *symbol = NULL, *event = NULL, *group = NULL;
Masami Hiramatsuda346342010-08-27 20:39:12 +0900444 char *arg;
Masami Hiramatsu2fba0c82009-09-10 19:53:14 -0400445 unsigned long offset = 0;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400446 void *addr = NULL;
Masami Hiramatsu4a846b42009-09-11 05:31:21 +0200447 char buf[MAX_EVENT_NAME_LEN];
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400448
Masami Hiramatsua7c312b2009-12-08 17:03:16 -0500449 /* argc must be >= 1 */
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400450 if (argv[0][0] == 'p')
Srikar Dronamraju3a6b7662012-04-09 14:41:33 +0530451 is_return = false;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400452 else if (argv[0][0] == 'r')
Srikar Dronamraju3a6b7662012-04-09 14:41:33 +0530453 is_return = true;
Masami Hiramatsua7c312b2009-12-08 17:03:16 -0500454 else if (argv[0][0] == '-')
Srikar Dronamraju3a6b7662012-04-09 14:41:33 +0530455 is_delete = true;
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400456 else {
Masami Hiramatsua7c312b2009-12-08 17:03:16 -0500457 pr_info("Probe definition must be started with 'p', 'r' or"
458 " '-'.\n");
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400459 return -EINVAL;
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400460 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400461
462 if (argv[0][1] == ':') {
463 event = &argv[0][2];
Masami Hiramatsuf52487e2009-09-10 19:53:53 -0400464 if (strchr(event, '/')) {
465 group = event;
466 event = strchr(group, '/') + 1;
467 event[-1] = '\0';
468 if (strlen(group) == 0) {
Wenji Huanga5efd922010-02-24 15:40:23 +0800469 pr_info("Group name is not specified\n");
Masami Hiramatsuf52487e2009-09-10 19:53:53 -0400470 return -EINVAL;
471 }
472 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400473 if (strlen(event) == 0) {
Wenji Huanga5efd922010-02-24 15:40:23 +0800474 pr_info("Event name is not specified\n");
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400475 return -EINVAL;
476 }
477 }
Masami Hiramatsua7c312b2009-12-08 17:03:16 -0500478 if (!group)
479 group = KPROBE_EVENT_SYSTEM;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400480
Masami Hiramatsua7c312b2009-12-08 17:03:16 -0500481 if (is_delete) {
482 if (!event) {
483 pr_info("Delete command needs an event name.\n");
484 return -EINVAL;
485 }
Srikar Dronamraju9da79ab2010-06-30 14:15:48 +0530486 mutex_lock(&probe_lock);
Masami Hiramatsu7143f162011-06-27 16:26:36 +0900487 tp = find_trace_probe(event, group);
Masami Hiramatsua7c312b2009-12-08 17:03:16 -0500488 if (!tp) {
Srikar Dronamraju9da79ab2010-06-30 14:15:48 +0530489 mutex_unlock(&probe_lock);
Masami Hiramatsua7c312b2009-12-08 17:03:16 -0500490 pr_info("Event %s/%s doesn't exist.\n", group, event);
491 return -ENOENT;
492 }
493 /* delete an event */
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900494 ret = unregister_trace_probe(tp);
495 if (ret == 0)
496 free_trace_probe(tp);
Srikar Dronamraju9da79ab2010-06-30 14:15:48 +0530497 mutex_unlock(&probe_lock);
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900498 return ret;
Masami Hiramatsua7c312b2009-12-08 17:03:16 -0500499 }
500
501 if (argc < 2) {
502 pr_info("Probe point is not specified.\n");
503 return -EINVAL;
504 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400505 if (isdigit(argv[1][0])) {
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400506 if (is_return) {
507 pr_info("Return probe point must be a symbol.\n");
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400508 return -EINVAL;
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400509 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400510 /* an address specified */
Daniel Walterbcd83ea2012-09-26 22:08:38 +0200511 ret = kstrtoul(&argv[1][0], 0, (unsigned long *)&addr);
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400512 if (ret) {
513 pr_info("Failed to parse address.\n");
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400514 return ret;
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400515 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400516 } else {
517 /* a symbol specified */
518 symbol = argv[1];
519 /* TODO: support .init module functions */
Srikar Dronamraju8ab83f52012-04-09 14:41:44 +0530520 ret = traceprobe_split_symbol_offset(symbol, &offset);
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400521 if (ret) {
522 pr_info("Failed to parse symbol.\n");
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400523 return ret;
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400524 }
525 if (offset && is_return) {
526 pr_info("Return probe must be used without offset.\n");
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400527 return -EINVAL;
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400528 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400529 }
Masami Hiramatsua82378d2009-08-13 16:35:18 -0400530 argc -= 2; argv += 2;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400531
532 /* setup a probe */
Masami Hiramatsu42635652009-08-13 16:35:26 -0400533 if (!event) {
534 /* Make a new event name */
Masami Hiramatsu42635652009-08-13 16:35:26 -0400535 if (symbol)
Masami Hiramatsu6f3cf442009-12-16 17:24:08 -0500536 snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_%ld",
Masami Hiramatsu42635652009-08-13 16:35:26 -0400537 is_return ? 'r' : 'p', symbol, offset);
538 else
Masami Hiramatsu6f3cf442009-12-16 17:24:08 -0500539 snprintf(buf, MAX_EVENT_NAME_LEN, "%c_0x%p",
Masami Hiramatsu42635652009-08-13 16:35:26 -0400540 is_return ? 'r' : 'p', addr);
Masami Hiramatsu4a846b42009-09-11 05:31:21 +0200541 event = buf;
542 }
Masami Hiramatsuf52487e2009-09-10 19:53:53 -0400543 tp = alloc_trace_probe(group, event, addr, symbol, offset, argc,
544 is_return);
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400545 if (IS_ERR(tp)) {
546 pr_info("Failed to allocate trace_probe.(%d)\n",
547 (int)PTR_ERR(tp));
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400548 return PTR_ERR(tp);
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400549 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400550
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400551 /* parse arguments */
Masami Hiramatsua82378d2009-08-13 16:35:18 -0400552 ret = 0;
553 for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
Masami Hiramatsu61a52732010-08-27 20:38:46 +0900554 /* Increment count for freeing args in error case */
555 tp->nr_args++;
556
Masami Hiramatsueca0d912009-09-10 19:53:38 -0400557 /* Parse argument name */
558 arg = strchr(argv[i], '=');
Masami Hiramatsuaba91592010-08-27 20:39:06 +0900559 if (arg) {
Masami Hiramatsueca0d912009-09-10 19:53:38 -0400560 *arg++ = '\0';
Masami Hiramatsuaba91592010-08-27 20:39:06 +0900561 tp->args[i].name = kstrdup(argv[i], GFP_KERNEL);
562 } else {
Masami Hiramatsueca0d912009-09-10 19:53:38 -0400563 arg = argv[i];
Masami Hiramatsuaba91592010-08-27 20:39:06 +0900564 /* If argument name is omitted, set "argN" */
565 snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1);
566 tp->args[i].name = kstrdup(buf, GFP_KERNEL);
567 }
Masami Hiramatsua703d942009-10-07 18:28:07 -0400568
Masami Hiramatsuba8665d2009-11-30 19:19:20 -0500569 if (!tp->args[i].name) {
Masami Hiramatsuaba91592010-08-27 20:39:06 +0900570 pr_info("Failed to allocate argument[%d] name.\n", i);
Masami Hiramatsuba8665d2009-11-30 19:19:20 -0500571 ret = -ENOMEM;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400572 goto error;
573 }
Masami Hiramatsuda346342010-08-27 20:39:12 +0900574
575 if (!is_good_name(tp->args[i].name)) {
576 pr_info("Invalid argument[%d] name: %s\n",
577 i, tp->args[i].name);
578 ret = -EINVAL;
579 goto error;
580 }
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400581
Srikar Dronamraju8ab83f52012-04-09 14:41:44 +0530582 if (traceprobe_conflict_field_name(tp->args[i].name,
583 tp->args, i)) {
Masami Hiramatsuaba91592010-08-27 20:39:06 +0900584 pr_info("Argument[%d] name '%s' conflicts with "
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400585 "another field.\n", i, argv[i]);
586 ret = -EINVAL;
587 goto error;
588 }
Masami Hiramatsuba8665d2009-11-30 19:19:20 -0500589
590 /* Parse fetch argument */
Srikar Dronamraju8ab83f52012-04-09 14:41:44 +0530591 ret = traceprobe_parse_probe_arg(arg, &tp->size, &tp->args[i],
Srikar Dronamrajuf3f096c2012-04-11 16:00:43 +0530592 is_return, true);
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400593 if (ret) {
Masami Hiramatsuaba91592010-08-27 20:39:06 +0900594 pr_info("Parse error at argument[%d]. (%d)\n", i, ret);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400595 goto error;
Masami Hiramatsue63cc232009-10-16 20:07:28 -0400596 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400597 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400598
599 ret = register_trace_probe(tp);
600 if (ret)
601 goto error;
602 return 0;
603
604error:
605 free_trace_probe(tp);
606 return ret;
607}
608
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900609static int release_all_trace_probes(void)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400610{
611 struct trace_probe *tp;
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900612 int ret = 0;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400613
614 mutex_lock(&probe_lock);
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900615 /* Ensure no probe is in use. */
616 list_for_each_entry(tp, &probe_list, list)
617 if (trace_probe_is_enabled(tp)) {
618 ret = -EBUSY;
619 goto end;
620 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400621 /* TODO: Use batch unregistration */
622 while (!list_empty(&probe_list)) {
623 tp = list_entry(probe_list.next, struct trace_probe, list);
624 unregister_trace_probe(tp);
625 free_trace_probe(tp);
626 }
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900627
628end:
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400629 mutex_unlock(&probe_lock);
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900630
631 return ret;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400632}
633
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400634/* Probes listing interfaces */
635static void *probes_seq_start(struct seq_file *m, loff_t *pos)
636{
637 mutex_lock(&probe_lock);
638 return seq_list_start(&probe_list, *pos);
639}
640
641static void *probes_seq_next(struct seq_file *m, void *v, loff_t *pos)
642{
643 return seq_list_next(v, &probe_list, pos);
644}
645
646static void probes_seq_stop(struct seq_file *m, void *v)
647{
648 mutex_unlock(&probe_lock);
649}
650
651static int probes_seq_show(struct seq_file *m, void *v)
652{
653 struct trace_probe *tp = v;
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400654 int i;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400655
Masami Hiramatsu7143f162011-06-27 16:26:36 +0900656 seq_printf(m, "%c", trace_probe_is_return(tp) ? 'r' : 'p');
Steven Rostedt8f082012010-04-20 10:47:33 -0400657 seq_printf(m, ":%s/%s", tp->call.class->system, tp->call.name);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400658
Lai Jiangshan52a11f32009-11-25 16:33:15 +0800659 if (!tp->symbol)
660 seq_printf(m, " 0x%p", tp->rp.kp.addr);
661 else if (tp->rp.kp.offset)
Masami Hiramatsu7143f162011-06-27 16:26:36 +0900662 seq_printf(m, " %s+%u", trace_probe_symbol(tp),
663 tp->rp.kp.offset);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400664 else
Masami Hiramatsu7143f162011-06-27 16:26:36 +0900665 seq_printf(m, " %s", trace_probe_symbol(tp));
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400666
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400667 for (i = 0; i < tp->nr_args; i++)
668 seq_printf(m, " %s=%s", tp->args[i].name, tp->args[i].comm);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400669 seq_printf(m, "\n");
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400670
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400671 return 0;
672}
673
674static const struct seq_operations probes_seq_op = {
675 .start = probes_seq_start,
676 .next = probes_seq_next,
677 .stop = probes_seq_stop,
678 .show = probes_seq_show
679};
680
681static int probes_open(struct inode *inode, struct file *file)
682{
Masami Hiramatsu02ca1522011-10-04 19:44:38 +0900683 int ret;
684
685 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
686 ret = release_all_trace_probes();
687 if (ret < 0)
688 return ret;
689 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400690
691 return seq_open(file, &probes_seq_op);
692}
693
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400694static ssize_t probes_write(struct file *file, const char __user *buffer,
695 size_t count, loff_t *ppos)
696{
Srikar Dronamraju8ab83f52012-04-09 14:41:44 +0530697 return traceprobe_probes_write(file, buffer, count, ppos,
698 create_trace_probe);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400699}
700
701static const struct file_operations kprobe_events_ops = {
702 .owner = THIS_MODULE,
703 .open = probes_open,
704 .read = seq_read,
705 .llseek = seq_lseek,
706 .release = seq_release,
707 .write = probes_write,
708};
709
Masami Hiramatsucd7e7bd2009-08-13 16:35:42 -0400710/* Probes profiling interfaces */
711static int probes_profile_seq_show(struct seq_file *m, void *v)
712{
713 struct trace_probe *tp = v;
714
715 seq_printf(m, " %-44s %15lu %15lu\n", tp->call.name, tp->nhit,
Masami Hiramatsu4a846b42009-09-11 05:31:21 +0200716 tp->rp.kp.nmissed);
Masami Hiramatsucd7e7bd2009-08-13 16:35:42 -0400717
718 return 0;
719}
720
721static const struct seq_operations profile_seq_op = {
722 .start = probes_seq_start,
723 .next = probes_seq_next,
724 .stop = probes_seq_stop,
725 .show = probes_profile_seq_show
726};
727
728static int profile_open(struct inode *inode, struct file *file)
729{
730 return seq_open(file, &profile_seq_op);
731}
732
733static const struct file_operations kprobe_profile_ops = {
734 .owner = THIS_MODULE,
735 .open = profile_open,
736 .read = seq_read,
737 .llseek = seq_lseek,
738 .release = seq_release,
739};
740
Masami Hiramatsue09c8612010-07-05 15:54:45 -0300741/* Sum up total data length for dynamic arraies (strings) */
742static __kprobes int __get_data_size(struct trace_probe *tp,
743 struct pt_regs *regs)
744{
745 int i, ret = 0;
746 u32 len;
747
748 for (i = 0; i < tp->nr_args; i++)
749 if (unlikely(tp->args[i].fetch_size.fn)) {
750 call_fetch(&tp->args[i].fetch_size, regs, &len);
751 ret += len;
752 }
753
754 return ret;
755}
756
757/* Store the value of each argument */
758static __kprobes void store_trace_args(int ent_size, struct trace_probe *tp,
759 struct pt_regs *regs,
760 u8 *data, int maxlen)
761{
762 int i;
763 u32 end = tp->size;
764 u32 *dl; /* Data (relative) location */
765
766 for (i = 0; i < tp->nr_args; i++) {
767 if (unlikely(tp->args[i].fetch_size.fn)) {
768 /*
769 * First, we set the relative location and
770 * maximum data length to *dl
771 */
772 dl = (u32 *)(data + tp->args[i].offset);
773 *dl = make_data_rloc(maxlen, end - tp->args[i].offset);
774 /* Then try to fetch string or dynamic array data */
775 call_fetch(&tp->args[i].fetch, regs, dl);
776 /* Reduce maximum length */
777 end += get_rloc_len(*dl);
778 maxlen -= get_rloc_len(*dl);
779 /* Trick here, convert data_rloc to data_loc */
780 *dl = convert_rloc_to_loc(*dl,
781 ent_size + tp->args[i].offset);
782 } else
783 /* Just fetching data normally */
784 call_fetch(&tp->args[i].fetch, regs,
785 data + tp->args[i].offset);
786 }
787}
788
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400789/* Kprobe handler */
Masami Hiramatsu2b106aa2013-05-09 14:44:41 +0900790static __kprobes void
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900791__kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs,
792 struct ftrace_event_file *ftrace_file)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400793{
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400794 struct kprobe_trace_entry_head *entry;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400795 struct ring_buffer_event *event;
Frederic Weisbecker8f8ffe22009-09-11 01:09:23 +0200796 struct ring_buffer *buffer;
Masami Hiramatsue09c8612010-07-05 15:54:45 -0300797 int size, dsize, pc;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400798 unsigned long irq_flags;
Masami Hiramatsu42635652009-08-13 16:35:26 -0400799 struct ftrace_event_call *call = &tp->call;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400800
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900801 WARN_ON(call != ftrace_file->event_call);
802
Masami Hiramatsub8820082013-05-09 14:44:54 +0900803 if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags))
804 return;
805
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400806 local_save_flags(irq_flags);
807 pc = preempt_count();
808
Masami Hiramatsue09c8612010-07-05 15:54:45 -0300809 dsize = __get_data_size(tp, regs);
810 size = sizeof(*entry) + tp->size + dsize;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400811
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900812 event = trace_event_buffer_lock_reserve(&buffer, ftrace_file,
813 call->event.type,
814 size, irq_flags, pc);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400815 if (!event)
Xiao Guangrong1e12a4a2010-01-28 09:34:27 +0800816 return;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400817
818 entry = ring_buffer_event_data(event);
Masami Hiramatsu2b106aa2013-05-09 14:44:41 +0900819 entry->ip = (unsigned long)tp->rp.kp.addr;
Masami Hiramatsue09c8612010-07-05 15:54:45 -0300820 store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400821
Frederic Weisbecker8f8ffe22009-09-11 01:09:23 +0200822 if (!filter_current_check_discard(buffer, call, entry, event))
Steven Rostedt0d5c6e12012-11-01 20:54:21 -0400823 trace_buffer_unlock_commit_regs(buffer, event,
824 irq_flags, pc, regs);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400825}
826
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900827static __kprobes void
828kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs)
829{
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200830 struct event_file_link *link;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900831
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200832 list_for_each_entry_rcu(link, &tp->files, list)
833 __kprobe_trace_func(tp, regs, link->file);
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900834}
835
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400836/* Kretprobe handler */
Masami Hiramatsu2b106aa2013-05-09 14:44:41 +0900837static __kprobes void
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900838__kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri,
839 struct pt_regs *regs,
840 struct ftrace_event_file *ftrace_file)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400841{
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400842 struct kretprobe_trace_entry_head *entry;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400843 struct ring_buffer_event *event;
Frederic Weisbecker8f8ffe22009-09-11 01:09:23 +0200844 struct ring_buffer *buffer;
Masami Hiramatsue09c8612010-07-05 15:54:45 -0300845 int size, pc, dsize;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400846 unsigned long irq_flags;
Masami Hiramatsu42635652009-08-13 16:35:26 -0400847 struct ftrace_event_call *call = &tp->call;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400848
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900849 WARN_ON(call != ftrace_file->event_call);
850
Masami Hiramatsub8820082013-05-09 14:44:54 +0900851 if (test_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &ftrace_file->flags))
852 return;
853
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400854 local_save_flags(irq_flags);
855 pc = preempt_count();
856
Masami Hiramatsue09c8612010-07-05 15:54:45 -0300857 dsize = __get_data_size(tp, regs);
858 size = sizeof(*entry) + tp->size + dsize;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400859
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900860 event = trace_event_buffer_lock_reserve(&buffer, ftrace_file,
861 call->event.type,
862 size, irq_flags, pc);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400863 if (!event)
Xiao Guangrong1e12a4a2010-01-28 09:34:27 +0800864 return;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400865
866 entry = ring_buffer_event_data(event);
Masami Hiramatsu4a846b42009-09-11 05:31:21 +0200867 entry->func = (unsigned long)tp->rp.kp.addr;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400868 entry->ret_ip = (unsigned long)ri->ret_addr;
Masami Hiramatsue09c8612010-07-05 15:54:45 -0300869 store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400870
Frederic Weisbecker8f8ffe22009-09-11 01:09:23 +0200871 if (!filter_current_check_discard(buffer, call, entry, event))
Steven Rostedt0d5c6e12012-11-01 20:54:21 -0400872 trace_buffer_unlock_commit_regs(buffer, event,
873 irq_flags, pc, regs);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400874}
875
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900876static __kprobes void
877kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri,
878 struct pt_regs *regs)
879{
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200880 struct event_file_link *link;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900881
Oleg Nesterovb04d52e2013-06-20 19:38:14 +0200882 list_for_each_entry_rcu(link, &tp->files, list)
883 __kretprobe_trace_func(tp, ri, regs, link->file);
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +0900884}
885
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400886/* Event entry printers */
Masami Hiramatsub62fdd92013-05-13 20:58:39 +0900887static enum print_line_t
Steven Rostedta9a57762010-04-22 18:46:14 -0400888print_kprobe_event(struct trace_iterator *iter, int flags,
889 struct trace_event *event)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400890{
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400891 struct kprobe_trace_entry_head *field;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400892 struct trace_seq *s = &iter->seq;
Masami Hiramatsueca0d912009-09-10 19:53:38 -0400893 struct trace_probe *tp;
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400894 u8 *data;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400895 int i;
896
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400897 field = (struct kprobe_trace_entry_head *)iter->ent;
Steven Rostedt80decc72010-04-23 10:00:22 -0400898 tp = container_of(event, struct trace_probe, call.event);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400899
Masami Hiramatsu6e9f23d2009-09-10 19:53:45 -0400900 if (!trace_seq_printf(s, "%s: (", tp->call.name))
901 goto partial;
902
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400903 if (!seq_print_ip_sym(s, field->ip, flags | TRACE_ITER_SYM_OFFSET))
904 goto partial;
905
Masami Hiramatsu6e9f23d2009-09-10 19:53:45 -0400906 if (!trace_seq_puts(s, ")"))
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400907 goto partial;
908
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400909 data = (u8 *)&field[1];
910 for (i = 0; i < tp->nr_args; i++)
911 if (!tp->args[i].type->print(s, tp->args[i].name,
Masami Hiramatsue09c8612010-07-05 15:54:45 -0300912 data + tp->args[i].offset, field))
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400913 goto partial;
914
915 if (!trace_seq_puts(s, "\n"))
916 goto partial;
917
918 return TRACE_TYPE_HANDLED;
919partial:
920 return TRACE_TYPE_PARTIAL_LINE;
921}
922
Masami Hiramatsub62fdd92013-05-13 20:58:39 +0900923static enum print_line_t
Steven Rostedta9a57762010-04-22 18:46:14 -0400924print_kretprobe_event(struct trace_iterator *iter, int flags,
925 struct trace_event *event)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400926{
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400927 struct kretprobe_trace_entry_head *field;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400928 struct trace_seq *s = &iter->seq;
Masami Hiramatsueca0d912009-09-10 19:53:38 -0400929 struct trace_probe *tp;
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400930 u8 *data;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400931 int i;
932
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400933 field = (struct kretprobe_trace_entry_head *)iter->ent;
Steven Rostedt80decc72010-04-23 10:00:22 -0400934 tp = container_of(event, struct trace_probe, call.event);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400935
Masami Hiramatsu6e9f23d2009-09-10 19:53:45 -0400936 if (!trace_seq_printf(s, "%s: (", tp->call.name))
937 goto partial;
938
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400939 if (!seq_print_ip_sym(s, field->ret_ip, flags | TRACE_ITER_SYM_OFFSET))
940 goto partial;
941
942 if (!trace_seq_puts(s, " <- "))
943 goto partial;
944
945 if (!seq_print_ip_sym(s, field->func, flags & ~TRACE_ITER_SYM_OFFSET))
946 goto partial;
947
Masami Hiramatsu6e9f23d2009-09-10 19:53:45 -0400948 if (!trace_seq_puts(s, ")"))
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400949 goto partial;
950
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400951 data = (u8 *)&field[1];
952 for (i = 0; i < tp->nr_args; i++)
953 if (!tp->args[i].type->print(s, tp->args[i].name,
Masami Hiramatsue09c8612010-07-05 15:54:45 -0300954 data + tp->args[i].offset, field))
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400955 goto partial;
956
957 if (!trace_seq_puts(s, "\n"))
958 goto partial;
959
960 return TRACE_TYPE_HANDLED;
961partial:
962 return TRACE_TYPE_PARTIAL_LINE;
963}
964
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400965
966static int kprobe_event_define_fields(struct ftrace_event_call *event_call)
967{
968 int ret, i;
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400969 struct kprobe_trace_entry_head field;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400970 struct trace_probe *tp = (struct trace_probe *)event_call->data;
971
Masami Hiramatsua703d942009-10-07 18:28:07 -0400972 DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0);
Masami Hiramatsueca0d912009-09-10 19:53:38 -0400973 /* Set argument names as fields */
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400974 for (i = 0; i < tp->nr_args; i++) {
Masami Hiramatsue09c8612010-07-05 15:54:45 -0300975 ret = trace_define_field(event_call, tp->args[i].type->fmttype,
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400976 tp->args[i].name,
977 sizeof(field) + tp->args[i].offset,
978 tp->args[i].type->size,
979 tp->args[i].type->is_signed,
980 FILTER_OTHER);
981 if (ret)
982 return ret;
983 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400984 return 0;
985}
986
987static int kretprobe_event_define_fields(struct ftrace_event_call *event_call)
988{
989 int ret, i;
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400990 struct kretprobe_trace_entry_head field;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -0400991 struct trace_probe *tp = (struct trace_probe *)event_call->data;
992
Masami Hiramatsua703d942009-10-07 18:28:07 -0400993 DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0);
994 DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0);
Masami Hiramatsueca0d912009-09-10 19:53:38 -0400995 /* Set argument names as fields */
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400996 for (i = 0; i < tp->nr_args; i++) {
Masami Hiramatsue09c8612010-07-05 15:54:45 -0300997 ret = trace_define_field(event_call, tp->args[i].type->fmttype,
Masami Hiramatsu93ccae72010-04-12 13:17:08 -0400998 tp->args[i].name,
999 sizeof(field) + tp->args[i].offset,
1000 tp->args[i].type->size,
1001 tp->args[i].type->is_signed,
1002 FILTER_OTHER);
1003 if (ret)
1004 return ret;
1005 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001006 return 0;
1007}
1008
Lai Jiangshana342a0282009-12-15 15:39:49 +08001009static int __set_print_fmt(struct trace_probe *tp, char *buf, int len)
1010{
1011 int i;
1012 int pos = 0;
1013
1014 const char *fmt, *arg;
1015
Masami Hiramatsu7143f162011-06-27 16:26:36 +09001016 if (!trace_probe_is_return(tp)) {
Lai Jiangshana342a0282009-12-15 15:39:49 +08001017 fmt = "(%lx)";
1018 arg = "REC->" FIELD_STRING_IP;
1019 } else {
1020 fmt = "(%lx <- %lx)";
1021 arg = "REC->" FIELD_STRING_FUNC ", REC->" FIELD_STRING_RETIP;
1022 }
1023
1024 /* When len=0, we just calculate the needed length */
1025#define LEN_OR_ZERO (len ? len - pos : 0)
1026
1027 pos += snprintf(buf + pos, LEN_OR_ZERO, "\"%s", fmt);
1028
1029 for (i = 0; i < tp->nr_args; i++) {
Masami Hiramatsu93ccae72010-04-12 13:17:08 -04001030 pos += snprintf(buf + pos, LEN_OR_ZERO, " %s=%s",
1031 tp->args[i].name, tp->args[i].type->fmt);
Lai Jiangshana342a0282009-12-15 15:39:49 +08001032 }
1033
1034 pos += snprintf(buf + pos, LEN_OR_ZERO, "\", %s", arg);
1035
1036 for (i = 0; i < tp->nr_args; i++) {
Masami Hiramatsue09c8612010-07-05 15:54:45 -03001037 if (strcmp(tp->args[i].type->name, "string") == 0)
1038 pos += snprintf(buf + pos, LEN_OR_ZERO,
1039 ", __get_str(%s)",
1040 tp->args[i].name);
1041 else
1042 pos += snprintf(buf + pos, LEN_OR_ZERO, ", REC->%s",
1043 tp->args[i].name);
Lai Jiangshana342a0282009-12-15 15:39:49 +08001044 }
1045
1046#undef LEN_OR_ZERO
1047
1048 /* return the length of print_fmt */
1049 return pos;
1050}
1051
1052static int set_print_fmt(struct trace_probe *tp)
1053{
1054 int len;
1055 char *print_fmt;
1056
1057 /* First: called with 0 length to calculate the needed length */
1058 len = __set_print_fmt(tp, NULL, 0);
1059 print_fmt = kmalloc(len + 1, GFP_KERNEL);
1060 if (!print_fmt)
1061 return -ENOMEM;
1062
1063 /* Second: actually write the @print_fmt */
1064 __set_print_fmt(tp, print_fmt, len + 1);
1065 tp->call.print_fmt = print_fmt;
1066
1067 return 0;
1068}
1069
Li Zefan07b139c2009-12-21 14:27:35 +08001070#ifdef CONFIG_PERF_EVENTS
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001071
1072/* Kprobe profile handler */
Masami Hiramatsu2b106aa2013-05-09 14:44:41 +09001073static __kprobes void
1074kprobe_perf_func(struct trace_probe *tp, struct pt_regs *regs)
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001075{
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001076 struct ftrace_event_call *call = &tp->call;
Masami Hiramatsu93ccae72010-04-12 13:17:08 -04001077 struct kprobe_trace_entry_head *entry;
Peter Zijlstra1c024eca2010-05-19 14:02:22 +02001078 struct hlist_head *head;
Masami Hiramatsue09c8612010-07-05 15:54:45 -03001079 int size, __size, dsize;
Peter Zijlstra4ed7c922009-11-23 11:37:29 +01001080 int rctx;
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001081
Oleg Nesterov288e9842013-06-20 19:38:06 +02001082 head = this_cpu_ptr(call->perf_events);
1083 if (hlist_empty(head))
1084 return;
1085
Masami Hiramatsue09c8612010-07-05 15:54:45 -03001086 dsize = __get_data_size(tp, regs);
1087 __size = sizeof(*entry) + tp->size + dsize;
Masami Hiramatsu74ebb632009-09-14 16:49:28 -04001088 size = ALIGN(__size + sizeof(u32), sizeof(u64));
1089 size -= sizeof(u32);
Frederic Weisbecker97d5a222010-03-05 05:35:37 +01001090 if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
Masami Hiramatsua1a138d2009-09-25 11:20:12 -07001091 "profile buffer not large enough"))
Xiao Guangrong1e12a4a2010-01-28 09:34:27 +08001092 return;
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001093
Steven Rostedtff5f1492010-05-21 11:49:57 -04001094 entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx);
Xiao Guangrong430ad5a2010-01-28 09:32:29 +08001095 if (!entry)
Xiao Guangrong1e12a4a2010-01-28 09:34:27 +08001096 return;
Frederic Weisbeckerce71b9d2009-11-22 05:26:55 +01001097
Masami Hiramatsu2b106aa2013-05-09 14:44:41 +09001098 entry->ip = (unsigned long)tp->rp.kp.addr;
Masami Hiramatsue09c8612010-07-05 15:54:45 -03001099 memset(&entry[1], 0, dsize);
1100 store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize);
Andrew Vagine6dab5f2012-07-11 18:14:58 +04001101 perf_trace_buf_submit(entry, size, rctx,
1102 entry->ip, 1, regs, head, NULL);
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001103}
1104
1105/* Kretprobe profile handler */
Masami Hiramatsu2b106aa2013-05-09 14:44:41 +09001106static __kprobes void
1107kretprobe_perf_func(struct trace_probe *tp, struct kretprobe_instance *ri,
1108 struct pt_regs *regs)
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001109{
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001110 struct ftrace_event_call *call = &tp->call;
Masami Hiramatsu93ccae72010-04-12 13:17:08 -04001111 struct kretprobe_trace_entry_head *entry;
Peter Zijlstra1c024eca2010-05-19 14:02:22 +02001112 struct hlist_head *head;
Masami Hiramatsue09c8612010-07-05 15:54:45 -03001113 int size, __size, dsize;
Peter Zijlstra4ed7c922009-11-23 11:37:29 +01001114 int rctx;
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001115
Oleg Nesterov288e9842013-06-20 19:38:06 +02001116 head = this_cpu_ptr(call->perf_events);
1117 if (hlist_empty(head))
1118 return;
1119
Masami Hiramatsue09c8612010-07-05 15:54:45 -03001120 dsize = __get_data_size(tp, regs);
1121 __size = sizeof(*entry) + tp->size + dsize;
Masami Hiramatsu74ebb632009-09-14 16:49:28 -04001122 size = ALIGN(__size + sizeof(u32), sizeof(u64));
1123 size -= sizeof(u32);
Frederic Weisbecker97d5a222010-03-05 05:35:37 +01001124 if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
Masami Hiramatsua1a138d2009-09-25 11:20:12 -07001125 "profile buffer not large enough"))
Xiao Guangrong1e12a4a2010-01-28 09:34:27 +08001126 return;
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001127
Steven Rostedtff5f1492010-05-21 11:49:57 -04001128 entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx);
Xiao Guangrong430ad5a2010-01-28 09:32:29 +08001129 if (!entry)
Xiao Guangrong1e12a4a2010-01-28 09:34:27 +08001130 return;
Frederic Weisbeckerce71b9d2009-11-22 05:26:55 +01001131
Masami Hiramatsua1a138d2009-09-25 11:20:12 -07001132 entry->func = (unsigned long)tp->rp.kp.addr;
1133 entry->ret_ip = (unsigned long)ri->ret_addr;
Masami Hiramatsue09c8612010-07-05 15:54:45 -03001134 store_trace_args(sizeof(*entry), tp, regs, (u8 *)&entry[1], dsize);
Andrew Vagine6dab5f2012-07-11 18:14:58 +04001135 perf_trace_buf_submit(entry, size, rctx,
1136 entry->ret_ip, 1, regs, head, NULL);
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001137}
Li Zefan07b139c2009-12-21 14:27:35 +08001138#endif /* CONFIG_PERF_EVENTS */
Masami Hiramatsu50d78052009-09-14 16:49:20 -04001139
Oleg Nesterov3fe3d612013-06-20 19:38:09 +02001140/*
1141 * called by perf_trace_init() or __ftrace_set_clr_event() under event_mutex.
1142 *
1143 * kprobe_trace_self_tests_init() does enable_trace_probe/disable_trace_probe
1144 * lockless, but we can't race with this __init function.
1145 */
Steven Rostedt22392912010-04-21 12:27:06 -04001146static __kprobes
Jiri Olsaceec0b62012-02-15 15:51:49 +01001147int kprobe_register(struct ftrace_event_call *event,
1148 enum trace_reg type, void *data)
Steven Rostedt22392912010-04-21 12:27:06 -04001149{
Masami Hiramatsu1538f882011-06-27 16:26:44 +09001150 struct trace_probe *tp = (struct trace_probe *)event->data;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001151 struct ftrace_event_file *file = data;
Masami Hiramatsu1538f882011-06-27 16:26:44 +09001152
Steven Rostedt22392912010-04-21 12:27:06 -04001153 switch (type) {
1154 case TRACE_REG_REGISTER:
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001155 return enable_trace_probe(tp, file);
Steven Rostedt22392912010-04-21 12:27:06 -04001156 case TRACE_REG_UNREGISTER:
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001157 return disable_trace_probe(tp, file);
Steven Rostedt22392912010-04-21 12:27:06 -04001158
1159#ifdef CONFIG_PERF_EVENTS
1160 case TRACE_REG_PERF_REGISTER:
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001161 return enable_trace_probe(tp, NULL);
Steven Rostedt22392912010-04-21 12:27:06 -04001162 case TRACE_REG_PERF_UNREGISTER:
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001163 return disable_trace_probe(tp, NULL);
Jiri Olsaceec0b62012-02-15 15:51:49 +01001164 case TRACE_REG_PERF_OPEN:
1165 case TRACE_REG_PERF_CLOSE:
Jiri Olsa489c75c2012-02-15 15:51:50 +01001166 case TRACE_REG_PERF_ADD:
1167 case TRACE_REG_PERF_DEL:
Jiri Olsaceec0b62012-02-15 15:51:49 +01001168 return 0;
Steven Rostedt22392912010-04-21 12:27:06 -04001169#endif
1170 }
1171 return 0;
1172}
Masami Hiramatsu50d78052009-09-14 16:49:20 -04001173
1174static __kprobes
1175int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs)
1176{
1177 struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp);
1178
Masami Hiramatsu48182bd2013-05-09 14:44:36 +09001179 tp->nhit++;
1180
Masami Hiramatsu50d78052009-09-14 16:49:20 -04001181 if (tp->flags & TP_FLAG_TRACE)
Masami Hiramatsu2b106aa2013-05-09 14:44:41 +09001182 kprobe_trace_func(tp, regs);
Li Zefan07b139c2009-12-21 14:27:35 +08001183#ifdef CONFIG_PERF_EVENTS
Masami Hiramatsu50d78052009-09-14 16:49:20 -04001184 if (tp->flags & TP_FLAG_PROFILE)
Masami Hiramatsu2b106aa2013-05-09 14:44:41 +09001185 kprobe_perf_func(tp, regs);
Li Zefan07b139c2009-12-21 14:27:35 +08001186#endif
Masami Hiramatsu50d78052009-09-14 16:49:20 -04001187 return 0; /* We don't tweek kernel, so just return 0 */
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001188}
1189
Masami Hiramatsu50d78052009-09-14 16:49:20 -04001190static __kprobes
1191int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs)
1192{
1193 struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp);
1194
Masami Hiramatsu48182bd2013-05-09 14:44:36 +09001195 tp->nhit++;
1196
Masami Hiramatsu50d78052009-09-14 16:49:20 -04001197 if (tp->flags & TP_FLAG_TRACE)
Masami Hiramatsu2b106aa2013-05-09 14:44:41 +09001198 kretprobe_trace_func(tp, ri, regs);
Li Zefan07b139c2009-12-21 14:27:35 +08001199#ifdef CONFIG_PERF_EVENTS
Masami Hiramatsu50d78052009-09-14 16:49:20 -04001200 if (tp->flags & TP_FLAG_PROFILE)
Masami Hiramatsu2b106aa2013-05-09 14:44:41 +09001201 kretprobe_perf_func(tp, ri, regs);
Li Zefan07b139c2009-12-21 14:27:35 +08001202#endif
Masami Hiramatsu50d78052009-09-14 16:49:20 -04001203 return 0; /* We don't tweek kernel, so just return 0 */
1204}
Masami Hiramatsue08d1c62009-09-10 19:53:30 -04001205
Steven Rostedta9a57762010-04-22 18:46:14 -04001206static struct trace_event_functions kretprobe_funcs = {
1207 .trace = print_kretprobe_event
1208};
1209
1210static struct trace_event_functions kprobe_funcs = {
1211 .trace = print_kprobe_event
1212};
1213
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001214static int register_probe_event(struct trace_probe *tp)
1215{
1216 struct ftrace_event_call *call = &tp->call;
1217 int ret;
1218
1219 /* Initialize ftrace_event_call */
Li Zefanffb9f992010-05-24 16:24:52 +08001220 INIT_LIST_HEAD(&call->class->fields);
Masami Hiramatsu7143f162011-06-27 16:26:36 +09001221 if (trace_probe_is_return(tp)) {
Steven Rostedt80decc72010-04-23 10:00:22 -04001222 call->event.funcs = &kretprobe_funcs;
Steven Rostedt2e33af02010-04-22 10:35:55 -04001223 call->class->define_fields = kretprobe_event_define_fields;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001224 } else {
Steven Rostedt80decc72010-04-23 10:00:22 -04001225 call->event.funcs = &kprobe_funcs;
Steven Rostedt2e33af02010-04-22 10:35:55 -04001226 call->class->define_fields = kprobe_event_define_fields;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001227 }
Lai Jiangshana342a0282009-12-15 15:39:49 +08001228 if (set_print_fmt(tp) < 0)
1229 return -ENOMEM;
Steven Rostedt32c0eda2010-04-23 10:38:03 -04001230 ret = register_ftrace_event(&call->event);
1231 if (!ret) {
Lai Jiangshana342a0282009-12-15 15:39:49 +08001232 kfree(call->print_fmt);
Masami Hiramatsuff50d992009-08-13 16:35:34 -04001233 return -ENODEV;
Lai Jiangshana342a0282009-12-15 15:39:49 +08001234 }
Steven Rostedt553552c2010-04-23 11:12:36 -04001235 call->flags = 0;
Steven Rostedt22392912010-04-21 12:27:06 -04001236 call->class->reg = kprobe_register;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001237 call->data = tp;
1238 ret = trace_add_event_call(call);
Masami Hiramatsuff50d992009-08-13 16:35:34 -04001239 if (ret) {
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001240 pr_info("Failed to register kprobe event: %s\n", call->name);
Lai Jiangshana342a0282009-12-15 15:39:49 +08001241 kfree(call->print_fmt);
Steven Rostedt80decc72010-04-23 10:00:22 -04001242 unregister_ftrace_event(&call->event);
Masami Hiramatsuff50d992009-08-13 16:35:34 -04001243 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001244 return ret;
1245}
1246
1247static void unregister_probe_event(struct trace_probe *tp)
1248{
Masami Hiramatsuff50d992009-08-13 16:35:34 -04001249 /* tp->event is unregistered in trace_remove_event_call() */
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001250 trace_remove_event_call(&tp->call);
Lai Jiangshana342a0282009-12-15 15:39:49 +08001251 kfree(tp->call.print_fmt);
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001252}
1253
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001254/* Make a debugfs interface for controlling probe points */
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001255static __init int init_kprobe_trace(void)
1256{
1257 struct dentry *d_tracer;
1258 struct dentry *entry;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001259
Masami Hiramatsu61424312011-06-27 16:26:56 +09001260 if (register_module_notifier(&trace_probe_module_nb))
1261 return -EINVAL;
1262
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001263 d_tracer = tracing_init_dentry();
1264 if (!d_tracer)
1265 return 0;
1266
1267 entry = debugfs_create_file("kprobe_events", 0644, d_tracer,
1268 NULL, &kprobe_events_ops);
1269
Masami Hiramatsucd7e7bd2009-08-13 16:35:42 -04001270 /* Event list interface */
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001271 if (!entry)
1272 pr_warning("Could not create debugfs "
1273 "'kprobe_events' entry\n");
Masami Hiramatsucd7e7bd2009-08-13 16:35:42 -04001274
1275 /* Profile interface */
1276 entry = debugfs_create_file("kprobe_profile", 0444, d_tracer,
1277 NULL, &kprobe_profile_ops);
1278
1279 if (!entry)
1280 pr_warning("Could not create debugfs "
1281 "'kprobe_profile' entry\n");
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001282 return 0;
1283}
1284fs_initcall(init_kprobe_trace);
1285
1286
1287#ifdef CONFIG_FTRACE_STARTUP_TEST
1288
Steven Rostedt265a5b72011-06-06 22:35:13 -04001289/*
1290 * The "__used" keeps gcc from removing the function symbol
1291 * from the kallsyms table.
1292 */
1293static __used int kprobe_trace_selftest_target(int a1, int a2, int a3,
1294 int a4, int a5, int a6)
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001295{
1296 return a1 + a2 + a3 + a4 + a5 + a6;
1297}
1298
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001299static struct ftrace_event_file *
1300find_trace_probe_file(struct trace_probe *tp, struct trace_array *tr)
1301{
1302 struct ftrace_event_file *file;
1303
1304 list_for_each_entry(file, &tr->events, list)
1305 if (file->event_call == &tp->call)
1306 return file;
1307
1308 return NULL;
1309}
1310
Oleg Nesterov3fe3d612013-06-20 19:38:09 +02001311/*
1312 * Nobody but us can call enable_trace_probe/disable_trace_probe at this
1313 * stage, we can do this lockless.
1314 */
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001315static __init int kprobe_trace_self_tests_init(void)
1316{
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001317 int ret, warn = 0;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001318 int (*target)(int, int, int, int, int, int);
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001319 struct trace_probe *tp;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001320 struct ftrace_event_file *file;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001321
1322 target = kprobe_trace_selftest_target;
1323
1324 pr_info("Testing kprobe tracing: ");
1325
Srikar Dronamraju8ab83f52012-04-09 14:41:44 +05301326 ret = traceprobe_command("p:testprobe kprobe_trace_selftest_target "
1327 "$stack $stack0 +0($stack)",
1328 create_trace_probe);
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001329 if (WARN_ON_ONCE(ret)) {
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001330 pr_warn("error on probing function entry.\n");
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001331 warn++;
1332 } else {
1333 /* Enable trace point */
Masami Hiramatsu7143f162011-06-27 16:26:36 +09001334 tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM);
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001335 if (WARN_ON_ONCE(tp == NULL)) {
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001336 pr_warn("error on getting new probe.\n");
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001337 warn++;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001338 } else {
1339 file = find_trace_probe_file(tp, top_trace_array());
1340 if (WARN_ON_ONCE(file == NULL)) {
1341 pr_warn("error on getting probe file.\n");
1342 warn++;
1343 } else
1344 enable_trace_probe(tp, file);
1345 }
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001346 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001347
Srikar Dronamraju8ab83f52012-04-09 14:41:44 +05301348 ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target "
1349 "$retval", create_trace_probe);
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001350 if (WARN_ON_ONCE(ret)) {
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001351 pr_warn("error on probing function return.\n");
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001352 warn++;
1353 } else {
1354 /* Enable trace point */
Masami Hiramatsu7143f162011-06-27 16:26:36 +09001355 tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM);
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001356 if (WARN_ON_ONCE(tp == NULL)) {
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001357 pr_warn("error on getting 2nd new probe.\n");
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001358 warn++;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001359 } else {
1360 file = find_trace_probe_file(tp, top_trace_array());
1361 if (WARN_ON_ONCE(file == NULL)) {
1362 pr_warn("error on getting probe file.\n");
1363 warn++;
1364 } else
1365 enable_trace_probe(tp, file);
1366 }
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001367 }
1368
1369 if (warn)
1370 goto end;
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001371
1372 ret = target(1, 2, 3, 4, 5, 6);
1373
Masami Hiramatsu02ca1522011-10-04 19:44:38 +09001374 /* Disable trace points before removing it */
1375 tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM);
1376 if (WARN_ON_ONCE(tp == NULL)) {
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001377 pr_warn("error on getting test probe.\n");
Masami Hiramatsu02ca1522011-10-04 19:44:38 +09001378 warn++;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001379 } else {
1380 file = find_trace_probe_file(tp, top_trace_array());
1381 if (WARN_ON_ONCE(file == NULL)) {
1382 pr_warn("error on getting probe file.\n");
1383 warn++;
1384 } else
1385 disable_trace_probe(tp, file);
1386 }
Masami Hiramatsu02ca1522011-10-04 19:44:38 +09001387
1388 tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM);
1389 if (WARN_ON_ONCE(tp == NULL)) {
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001390 pr_warn("error on getting 2nd test probe.\n");
Masami Hiramatsu02ca1522011-10-04 19:44:38 +09001391 warn++;
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001392 } else {
1393 file = find_trace_probe_file(tp, top_trace_array());
1394 if (WARN_ON_ONCE(file == NULL)) {
1395 pr_warn("error on getting probe file.\n");
1396 warn++;
1397 } else
1398 disable_trace_probe(tp, file);
1399 }
Masami Hiramatsu02ca1522011-10-04 19:44:38 +09001400
Srikar Dronamraju8ab83f52012-04-09 14:41:44 +05301401 ret = traceprobe_command("-:testprobe", create_trace_probe);
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001402 if (WARN_ON_ONCE(ret)) {
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001403 pr_warn("error on deleting a probe.\n");
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001404 warn++;
1405 }
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001406
Srikar Dronamraju8ab83f52012-04-09 14:41:44 +05301407 ret = traceprobe_command("-:testprobe2", create_trace_probe);
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001408 if (WARN_ON_ONCE(ret)) {
Masami Hiramatsu41a7dd42013-05-09 14:44:49 +09001409 pr_warn("error on deleting a probe.\n");
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001410 warn++;
1411 }
1412
1413end:
Masami Hiramatsu7143f162011-06-27 16:26:36 +09001414 release_all_trace_probes();
Masami Hiramatsu231e36f2010-01-14 00:12:12 -05001415 if (warn)
1416 pr_cont("NG: Some tests are failed. Please check them.\n");
1417 else
1418 pr_cont("OK\n");
Masami Hiramatsu413d37d2009-08-13 16:35:11 -04001419 return 0;
1420}
1421
1422late_initcall(kprobe_trace_self_tests_init);
1423
1424#endif