tracing/probes: Add fetch{,_size} member into deref fetch method
[deliverable/linux.git] / kernel / trace / trace_uprobe.c
CommitLineData
f3f096cf
SD
1/*
2 * uprobes-based tracing events
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Copyright (C) IBM Corporation, 2010-2012
18 * Author: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
19 */
20
21#include <linux/module.h>
22#include <linux/uaccess.h>
23#include <linux/uprobes.h>
24#include <linux/namei.h>
b2e902f0 25#include <linux/string.h>
f3f096cf
SD
26
27#include "trace_probe.h"
28
29#define UPROBE_EVENT_SYSTEM "uprobes"
30
457d1772
ON
31struct uprobe_trace_entry_head {
32 struct trace_entry ent;
33 unsigned long vaddr[];
34};
35
36#define SIZEOF_TRACE_ENTRY(is_return) \
37 (sizeof(struct uprobe_trace_entry_head) + \
38 sizeof(unsigned long) * (is_return ? 2 : 1))
39
40#define DATAOF_TRACE_ENTRY(entry, is_return) \
41 ((void*)(entry) + SIZEOF_TRACE_ENTRY(is_return))
42
736288ba
ON
43struct trace_uprobe_filter {
44 rwlock_t rwlock;
45 int nr_systemwide;
46 struct list_head perf_events;
47};
48
f3f096cf
SD
49/*
50 * uprobe event core functions
51 */
f3f096cf
SD
52struct trace_uprobe {
53 struct list_head list;
736288ba 54 struct trace_uprobe_filter filter;
a932b738 55 struct uprobe_consumer consumer;
f3f096cf
SD
56 struct inode *inode;
57 char *filename;
58 unsigned long offset;
59 unsigned long nhit;
14577c39 60 struct trace_probe tp;
f3f096cf
SD
61};
62
14577c39
NK
63#define SIZEOF_TRACE_UPROBE(n) \
64 (offsetof(struct trace_uprobe, tp.args) + \
f3f096cf
SD
65 (sizeof(struct probe_arg) * (n)))
66
67static int register_uprobe_event(struct trace_uprobe *tu);
c6c2401d 68static int unregister_uprobe_event(struct trace_uprobe *tu);
f3f096cf
SD
69
70static DEFINE_MUTEX(uprobe_lock);
71static LIST_HEAD(uprobe_list);
72
73static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs);
c1ae5c75
ON
74static int uretprobe_dispatcher(struct uprobe_consumer *con,
75 unsigned long func, struct pt_regs *regs);
f3f096cf 76
3fd996a2
NK
77#ifdef CONFIG_STACK_GROWSUP
78static unsigned long adjust_stack_addr(unsigned long addr, unsigned int n)
79{
80 return addr - (n * sizeof(long));
81}
82#else
83static unsigned long adjust_stack_addr(unsigned long addr, unsigned int n)
84{
85 return addr + (n * sizeof(long));
86}
87#endif
88
89static unsigned long get_user_stack_nth(struct pt_regs *regs, unsigned int n)
90{
91 unsigned long ret;
92 unsigned long addr = user_stack_pointer(regs);
93
94 addr = adjust_stack_addr(addr, n);
95
96 if (copy_from_user(&ret, (void __force __user *) addr, sizeof(ret)))
97 return 0;
98
99 return ret;
100}
101
102/*
103 * Uprobes-specific fetch functions
104 */
105#define DEFINE_FETCH_stack(type) \
106static __kprobes void FETCH_FUNC_NAME(stack, type)(struct pt_regs *regs,\
107 void *offset, void *dest) \
108{ \
109 *(type *)dest = (type)get_user_stack_nth(regs, \
110 ((unsigned long)offset)); \
111}
112DEFINE_BASIC_FETCH_FUNCS(stack)
113/* No string on the stack entry */
114#define fetch_stack_string NULL
115#define fetch_stack_string_size NULL
116
117
1301a44e
NK
118/* uprobes do not support symbol fetch methods */
119#define fetch_symbol_u8 NULL
120#define fetch_symbol_u16 NULL
121#define fetch_symbol_u32 NULL
122#define fetch_symbol_u64 NULL
123#define fetch_symbol_string NULL
124#define fetch_symbol_string_size NULL
125
34fee3a1
NK
126/* Fetch type information table */
127const struct fetch_type uprobes_fetch_type_table[] = {
128 /* Special types */
129 [FETCH_TYPE_STRING] = __ASSIGN_FETCH_TYPE("string", string, string,
130 sizeof(u32), 1, "__data_loc char[]"),
131 [FETCH_TYPE_STRSIZE] = __ASSIGN_FETCH_TYPE("string_size", u32,
132 string_size, sizeof(u32), 0, "u32"),
133 /* Basic types */
134 ASSIGN_FETCH_TYPE(u8, u8, 0),
135 ASSIGN_FETCH_TYPE(u16, u16, 0),
136 ASSIGN_FETCH_TYPE(u32, u32, 0),
137 ASSIGN_FETCH_TYPE(u64, u64, 0),
138 ASSIGN_FETCH_TYPE(s8, u8, 1),
139 ASSIGN_FETCH_TYPE(s16, u16, 1),
140 ASSIGN_FETCH_TYPE(s32, u32, 1),
141 ASSIGN_FETCH_TYPE(s64, u64, 1),
142
143 ASSIGN_FETCH_TYPE_END
144};
145
736288ba
ON
146static inline void init_trace_uprobe_filter(struct trace_uprobe_filter *filter)
147{
148 rwlock_init(&filter->rwlock);
149 filter->nr_systemwide = 0;
150 INIT_LIST_HEAD(&filter->perf_events);
151}
152
153static inline bool uprobe_filter_is_empty(struct trace_uprobe_filter *filter)
154{
155 return !filter->nr_systemwide && list_empty(&filter->perf_events);
156}
157
c1ae5c75
ON
158static inline bool is_ret_probe(struct trace_uprobe *tu)
159{
160 return tu->consumer.ret_handler != NULL;
161}
162
f3f096cf
SD
163/*
164 * Allocate new trace_uprobe and initialize it (including uprobes).
165 */
166static struct trace_uprobe *
c1ae5c75 167alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret)
f3f096cf
SD
168{
169 struct trace_uprobe *tu;
170
171 if (!event || !is_good_name(event))
172 return ERR_PTR(-EINVAL);
173
174 if (!group || !is_good_name(group))
175 return ERR_PTR(-EINVAL);
176
177 tu = kzalloc(SIZEOF_TRACE_UPROBE(nargs), GFP_KERNEL);
178 if (!tu)
179 return ERR_PTR(-ENOMEM);
180
14577c39
NK
181 tu->tp.call.class = &tu->tp.class;
182 tu->tp.call.name = kstrdup(event, GFP_KERNEL);
183 if (!tu->tp.call.name)
f3f096cf
SD
184 goto error;
185
14577c39
NK
186 tu->tp.class.system = kstrdup(group, GFP_KERNEL);
187 if (!tu->tp.class.system)
f3f096cf
SD
188 goto error;
189
190 INIT_LIST_HEAD(&tu->list);
a932b738 191 tu->consumer.handler = uprobe_dispatcher;
c1ae5c75
ON
192 if (is_ret)
193 tu->consumer.ret_handler = uretprobe_dispatcher;
736288ba 194 init_trace_uprobe_filter(&tu->filter);
14577c39 195 tu->tp.call.flags |= TRACE_EVENT_FL_USE_CALL_FILTER;
f3f096cf
SD
196 return tu;
197
198error:
14577c39 199 kfree(tu->tp.call.name);
f3f096cf
SD
200 kfree(tu);
201
202 return ERR_PTR(-ENOMEM);
203}
204
205static void free_trace_uprobe(struct trace_uprobe *tu)
206{
207 int i;
208
14577c39
NK
209 for (i = 0; i < tu->tp.nr_args; i++)
210 traceprobe_free_probe_arg(&tu->tp.args[i]);
f3f096cf
SD
211
212 iput(tu->inode);
14577c39
NK
213 kfree(tu->tp.call.class->system);
214 kfree(tu->tp.call.name);
f3f096cf
SD
215 kfree(tu->filename);
216 kfree(tu);
217}
218
219static struct trace_uprobe *find_probe_event(const char *event, const char *group)
220{
221 struct trace_uprobe *tu;
222
223 list_for_each_entry(tu, &uprobe_list, list)
14577c39
NK
224 if (strcmp(tu->tp.call.name, event) == 0 &&
225 strcmp(tu->tp.call.class->system, group) == 0)
f3f096cf
SD
226 return tu;
227
228 return NULL;
229}
230
231/* Unregister a trace_uprobe and probe_event: call with locking uprobe_lock */
c6c2401d 232static int unregister_trace_uprobe(struct trace_uprobe *tu)
f3f096cf 233{
c6c2401d
SRRH
234 int ret;
235
236 ret = unregister_uprobe_event(tu);
237 if (ret)
238 return ret;
239
f3f096cf 240 list_del(&tu->list);
f3f096cf 241 free_trace_uprobe(tu);
c6c2401d 242 return 0;
f3f096cf
SD
243}
244
245/* Register a trace_uprobe and probe_event */
246static int register_trace_uprobe(struct trace_uprobe *tu)
247{
14577c39 248 struct trace_uprobe *old_tu;
f3f096cf
SD
249 int ret;
250
251 mutex_lock(&uprobe_lock);
252
253 /* register as an event */
14577c39
NK
254 old_tu = find_probe_event(tu->tp.call.name, tu->tp.call.class->system);
255 if (old_tu) {
f3f096cf 256 /* delete old event */
14577c39 257 ret = unregister_trace_uprobe(old_tu);
c6c2401d
SRRH
258 if (ret)
259 goto end;
260 }
f3f096cf
SD
261
262 ret = register_uprobe_event(tu);
263 if (ret) {
264 pr_warning("Failed to register probe event(%d)\n", ret);
265 goto end;
266 }
267
268 list_add_tail(&tu->list, &uprobe_list);
269
270end:
271 mutex_unlock(&uprobe_lock);
272
273 return ret;
274}
275
276/*
277 * Argument syntax:
306cfe20 278 * - Add uprobe: p|r[:[GRP/]EVENT] PATH:OFFSET [FETCHARGS]
f3f096cf
SD
279 *
280 * - Remove uprobe: -:[GRP/]EVENT
281 */
282static int create_trace_uprobe(int argc, char **argv)
283{
284 struct trace_uprobe *tu;
285 struct inode *inode;
286 char *arg, *event, *group, *filename;
287 char buf[MAX_EVENT_NAME_LEN];
288 struct path path;
289 unsigned long offset;
4ee5a52e 290 bool is_delete, is_return;
f3f096cf
SD
291 int i, ret;
292
293 inode = NULL;
294 ret = 0;
295 is_delete = false;
4ee5a52e 296 is_return = false;
f3f096cf
SD
297 event = NULL;
298 group = NULL;
299
300 /* argc must be >= 1 */
301 if (argv[0][0] == '-')
302 is_delete = true;
4ee5a52e
ON
303 else if (argv[0][0] == 'r')
304 is_return = true;
f3f096cf 305 else if (argv[0][0] != 'p') {
4ee5a52e 306 pr_info("Probe definition must be started with 'p', 'r' or '-'.\n");
f3f096cf
SD
307 return -EINVAL;
308 }
309
310 if (argv[0][1] == ':') {
311 event = &argv[0][2];
312 arg = strchr(event, '/');
313
314 if (arg) {
315 group = event;
316 event = arg + 1;
317 event[-1] = '\0';
318
319 if (strlen(group) == 0) {
320 pr_info("Group name is not specified\n");
321 return -EINVAL;
322 }
323 }
324 if (strlen(event) == 0) {
325 pr_info("Event name is not specified\n");
326 return -EINVAL;
327 }
328 }
329 if (!group)
330 group = UPROBE_EVENT_SYSTEM;
331
332 if (is_delete) {
c6c2401d
SRRH
333 int ret;
334
f3f096cf
SD
335 if (!event) {
336 pr_info("Delete command needs an event name.\n");
337 return -EINVAL;
338 }
339 mutex_lock(&uprobe_lock);
340 tu = find_probe_event(event, group);
341
342 if (!tu) {
343 mutex_unlock(&uprobe_lock);
344 pr_info("Event %s/%s doesn't exist.\n", group, event);
345 return -ENOENT;
346 }
347 /* delete an event */
c6c2401d 348 ret = unregister_trace_uprobe(tu);
f3f096cf 349 mutex_unlock(&uprobe_lock);
c6c2401d 350 return ret;
f3f096cf
SD
351 }
352
353 if (argc < 2) {
354 pr_info("Probe point is not specified.\n");
355 return -EINVAL;
356 }
357 if (isdigit(argv[1][0])) {
358 pr_info("probe point must be have a filename.\n");
359 return -EINVAL;
360 }
361 arg = strchr(argv[1], ':');
fa44063f
J
362 if (!arg) {
363 ret = -EINVAL;
f3f096cf 364 goto fail_address_parse;
fa44063f 365 }
f3f096cf
SD
366
367 *arg++ = '\0';
368 filename = argv[1];
369 ret = kern_path(filename, LOOKUP_FOLLOW, &path);
370 if (ret)
371 goto fail_address_parse;
372
f3f096cf 373 inode = igrab(path.dentry->d_inode);
84d7ed79
ON
374 path_put(&path);
375
7e4e28c5 376 if (!inode || !S_ISREG(inode->i_mode)) {
d24d7dbf
JZ
377 ret = -EINVAL;
378 goto fail_address_parse;
379 }
f3f096cf 380
84d7ed79
ON
381 ret = kstrtoul(arg, 0, &offset);
382 if (ret)
383 goto fail_address_parse;
384
f3f096cf
SD
385 argc -= 2;
386 argv += 2;
387
388 /* setup a probe */
389 if (!event) {
b2e902f0 390 char *tail;
f3f096cf
SD
391 char *ptr;
392
b2e902f0
AS
393 tail = kstrdup(kbasename(filename), GFP_KERNEL);
394 if (!tail) {
f3f096cf
SD
395 ret = -ENOMEM;
396 goto fail_address_parse;
397 }
398
f3f096cf
SD
399 ptr = strpbrk(tail, ".-_");
400 if (ptr)
401 *ptr = '\0';
402
403 snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_0x%lx", 'p', tail, offset);
404 event = buf;
405 kfree(tail);
406 }
407
4ee5a52e 408 tu = alloc_trace_uprobe(group, event, argc, is_return);
f3f096cf
SD
409 if (IS_ERR(tu)) {
410 pr_info("Failed to allocate trace_uprobe.(%d)\n", (int)PTR_ERR(tu));
411 ret = PTR_ERR(tu);
412 goto fail_address_parse;
413 }
414 tu->offset = offset;
415 tu->inode = inode;
416 tu->filename = kstrdup(filename, GFP_KERNEL);
417
418 if (!tu->filename) {
419 pr_info("Failed to allocate filename.\n");
420 ret = -ENOMEM;
421 goto error;
422 }
423
424 /* parse arguments */
425 ret = 0;
426 for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
14577c39
NK
427 struct probe_arg *parg = &tu->tp.args[i];
428
f3f096cf 429 /* Increment count for freeing args in error case */
14577c39 430 tu->tp.nr_args++;
f3f096cf
SD
431
432 /* Parse argument name */
433 arg = strchr(argv[i], '=');
434 if (arg) {
435 *arg++ = '\0';
14577c39 436 parg->name = kstrdup(argv[i], GFP_KERNEL);
f3f096cf
SD
437 } else {
438 arg = argv[i];
439 /* If argument name is omitted, set "argN" */
440 snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1);
14577c39 441 parg->name = kstrdup(buf, GFP_KERNEL);
f3f096cf
SD
442 }
443
14577c39 444 if (!parg->name) {
f3f096cf
SD
445 pr_info("Failed to allocate argument[%d] name.\n", i);
446 ret = -ENOMEM;
447 goto error;
448 }
449
14577c39
NK
450 if (!is_good_name(parg->name)) {
451 pr_info("Invalid argument[%d] name: %s\n", i, parg->name);
f3f096cf
SD
452 ret = -EINVAL;
453 goto error;
454 }
455
14577c39 456 if (traceprobe_conflict_field_name(parg->name, tu->tp.args, i)) {
f3f096cf
SD
457 pr_info("Argument[%d] name '%s' conflicts with "
458 "another field.\n", i, argv[i]);
459 ret = -EINVAL;
460 goto error;
461 }
462
463 /* Parse fetch argument */
14577c39
NK
464 ret = traceprobe_parse_probe_arg(arg, &tu->tp.size, parg,
465 false, false);
f3f096cf
SD
466 if (ret) {
467 pr_info("Parse error at argument[%d]. (%d)\n", i, ret);
468 goto error;
469 }
470 }
471
472 ret = register_trace_uprobe(tu);
473 if (ret)
474 goto error;
475 return 0;
476
477error:
478 free_trace_uprobe(tu);
479 return ret;
480
481fail_address_parse:
482 if (inode)
483 iput(inode);
484
d24d7dbf 485 pr_info("Failed to parse address or file.\n");
f3f096cf
SD
486
487 return ret;
488}
489
c6c2401d 490static int cleanup_all_probes(void)
f3f096cf
SD
491{
492 struct trace_uprobe *tu;
c6c2401d 493 int ret = 0;
f3f096cf
SD
494
495 mutex_lock(&uprobe_lock);
496 while (!list_empty(&uprobe_list)) {
497 tu = list_entry(uprobe_list.next, struct trace_uprobe, list);
c6c2401d
SRRH
498 ret = unregister_trace_uprobe(tu);
499 if (ret)
500 break;
f3f096cf
SD
501 }
502 mutex_unlock(&uprobe_lock);
c6c2401d 503 return ret;
f3f096cf
SD
504}
505
506/* Probes listing interfaces */
507static void *probes_seq_start(struct seq_file *m, loff_t *pos)
508{
509 mutex_lock(&uprobe_lock);
510 return seq_list_start(&uprobe_list, *pos);
511}
512
513static void *probes_seq_next(struct seq_file *m, void *v, loff_t *pos)
514{
515 return seq_list_next(v, &uprobe_list, pos);
516}
517
518static void probes_seq_stop(struct seq_file *m, void *v)
519{
520 mutex_unlock(&uprobe_lock);
521}
522
523static int probes_seq_show(struct seq_file *m, void *v)
524{
525 struct trace_uprobe *tu = v;
3ede82dd 526 char c = is_ret_probe(tu) ? 'r' : 'p';
f3f096cf
SD
527 int i;
528
14577c39 529 seq_printf(m, "%c:%s/%s", c, tu->tp.call.class->system, tu->tp.call.name);
f3f096cf
SD
530 seq_printf(m, " %s:0x%p", tu->filename, (void *)tu->offset);
531
14577c39
NK
532 for (i = 0; i < tu->tp.nr_args; i++)
533 seq_printf(m, " %s=%s", tu->tp.args[i].name, tu->tp.args[i].comm);
f3f096cf
SD
534
535 seq_printf(m, "\n");
536 return 0;
537}
538
539static const struct seq_operations probes_seq_op = {
540 .start = probes_seq_start,
541 .next = probes_seq_next,
542 .stop = probes_seq_stop,
543 .show = probes_seq_show
544};
545
546static int probes_open(struct inode *inode, struct file *file)
547{
c6c2401d
SRRH
548 int ret;
549
550 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
551 ret = cleanup_all_probes();
552 if (ret)
553 return ret;
554 }
f3f096cf
SD
555
556 return seq_open(file, &probes_seq_op);
557}
558
559static ssize_t probes_write(struct file *file, const char __user *buffer,
560 size_t count, loff_t *ppos)
561{
562 return traceprobe_probes_write(file, buffer, count, ppos, create_trace_uprobe);
563}
564
565static const struct file_operations uprobe_events_ops = {
566 .owner = THIS_MODULE,
567 .open = probes_open,
568 .read = seq_read,
569 .llseek = seq_lseek,
570 .release = seq_release,
571 .write = probes_write,
572};
573
574/* Probes profiling interfaces */
575static int probes_profile_seq_show(struct seq_file *m, void *v)
576{
577 struct trace_uprobe *tu = v;
578
14577c39 579 seq_printf(m, " %s %-44s %15lu\n", tu->filename, tu->tp.call.name, tu->nhit);
f3f096cf
SD
580 return 0;
581}
582
583static const struct seq_operations profile_seq_op = {
584 .start = probes_seq_start,
585 .next = probes_seq_next,
586 .stop = probes_seq_stop,
587 .show = probes_profile_seq_show
588};
589
590static int profile_open(struct inode *inode, struct file *file)
591{
592 return seq_open(file, &profile_seq_op);
593}
594
595static const struct file_operations uprobe_profile_ops = {
596 .owner = THIS_MODULE,
597 .open = profile_open,
598 .read = seq_read,
599 .llseek = seq_lseek,
600 .release = seq_release,
601};
602
a51cc604
ON
603static void uprobe_trace_print(struct trace_uprobe *tu,
604 unsigned long func, struct pt_regs *regs)
f3f096cf
SD
605{
606 struct uprobe_trace_entry_head *entry;
607 struct ring_buffer_event *event;
608 struct ring_buffer *buffer;
457d1772 609 void *data;
0e3853d2 610 int size, i;
14577c39 611 struct ftrace_event_call *call = &tu->tp.call;
f3f096cf 612
393a736c 613 size = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
f3f096cf 614 event = trace_current_buffer_lock_reserve(&buffer, call->event.type,
14577c39 615 size + tu->tp.size, 0, 0);
f3f096cf 616 if (!event)
a51cc604 617 return;
f3f096cf
SD
618
619 entry = ring_buffer_event_data(event);
393a736c
ON
620 if (is_ret_probe(tu)) {
621 entry->vaddr[0] = func;
622 entry->vaddr[1] = instruction_pointer(regs);
623 data = DATAOF_TRACE_ENTRY(entry, true);
624 } else {
625 entry->vaddr[0] = instruction_pointer(regs);
626 data = DATAOF_TRACE_ENTRY(entry, false);
627 }
628
14577c39
NK
629 for (i = 0; i < tu->tp.nr_args; i++) {
630 call_fetch(&tu->tp.args[i].fetch, regs,
631 data + tu->tp.args[i].offset);
632 }
f3f096cf 633
f306cc82 634 if (!call_filter_check_discard(call, entry, buffer, event))
0e3853d2 635 trace_buffer_unlock_commit(buffer, event, 0, 0);
a51cc604 636}
f42d24a1 637
a51cc604
ON
638/* uprobe handler */
639static int uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs)
640{
393a736c
ON
641 if (!is_ret_probe(tu))
642 uprobe_trace_print(tu, 0, regs);
f42d24a1 643 return 0;
f3f096cf
SD
644}
645
c1ae5c75
ON
646static void uretprobe_trace_func(struct trace_uprobe *tu, unsigned long func,
647 struct pt_regs *regs)
648{
649 uprobe_trace_print(tu, func, regs);
650}
651
f3f096cf
SD
652/* Event entry printers */
653static enum print_line_t
654print_uprobe_event(struct trace_iterator *iter, int flags, struct trace_event *event)
655{
457d1772 656 struct uprobe_trace_entry_head *entry;
f3f096cf
SD
657 struct trace_seq *s = &iter->seq;
658 struct trace_uprobe *tu;
659 u8 *data;
660 int i;
661
457d1772 662 entry = (struct uprobe_trace_entry_head *)iter->ent;
14577c39 663 tu = container_of(event, struct trace_uprobe, tp.call.event);
f3f096cf 664
3ede82dd 665 if (is_ret_probe(tu)) {
14577c39 666 if (!trace_seq_printf(s, "%s: (0x%lx <- 0x%lx)", tu->tp.call.name,
3ede82dd
ON
667 entry->vaddr[1], entry->vaddr[0]))
668 goto partial;
669 data = DATAOF_TRACE_ENTRY(entry, true);
670 } else {
14577c39 671 if (!trace_seq_printf(s, "%s: (0x%lx)", tu->tp.call.name,
3ede82dd
ON
672 entry->vaddr[0]))
673 goto partial;
674 data = DATAOF_TRACE_ENTRY(entry, false);
675 }
f3f096cf 676
14577c39
NK
677 for (i = 0; i < tu->tp.nr_args; i++) {
678 struct probe_arg *parg = &tu->tp.args[i];
679
680 if (!parg->type->print(s, parg->name, data + parg->offset, entry))
f3f096cf
SD
681 goto partial;
682 }
683
684 if (trace_seq_puts(s, "\n"))
685 return TRACE_TYPE_HANDLED;
686
687partial:
688 return TRACE_TYPE_PARTIAL_LINE;
689}
690
31ba3348
ON
691typedef bool (*filter_func_t)(struct uprobe_consumer *self,
692 enum uprobe_filter_ctx ctx,
693 struct mm_struct *mm);
694
695static int
696probe_event_enable(struct trace_uprobe *tu, int flag, filter_func_t filter)
f3f096cf 697{
f3f096cf
SD
698 int ret = 0;
699
14577c39 700 if (trace_probe_is_enabled(&tu->tp))
f3f096cf
SD
701 return -EINTR;
702
736288ba
ON
703 WARN_ON(!uprobe_filter_is_empty(&tu->filter));
704
14577c39 705 tu->tp.flags |= flag;
31ba3348 706 tu->consumer.filter = filter;
a932b738
ON
707 ret = uprobe_register(tu->inode, tu->offset, &tu->consumer);
708 if (ret)
14577c39 709 tu->tp.flags &= ~flag;
f3f096cf 710
4161824f 711 return ret;
f3f096cf
SD
712}
713
714static void probe_event_disable(struct trace_uprobe *tu, int flag)
715{
14577c39 716 if (!trace_probe_is_enabled(&tu->tp))
f3f096cf
SD
717 return;
718
736288ba
ON
719 WARN_ON(!uprobe_filter_is_empty(&tu->filter));
720
a932b738 721 uprobe_unregister(tu->inode, tu->offset, &tu->consumer);
14577c39 722 tu->tp.flags &= ~flag;
f3f096cf
SD
723}
724
725static int uprobe_event_define_fields(struct ftrace_event_call *event_call)
726{
457d1772 727 int ret, i, size;
f3f096cf 728 struct uprobe_trace_entry_head field;
457d1772 729 struct trace_uprobe *tu = event_call->data;
f3f096cf 730
4d1298e2
ON
731 if (is_ret_probe(tu)) {
732 DEFINE_FIELD(unsigned long, vaddr[0], FIELD_STRING_FUNC, 0);
733 DEFINE_FIELD(unsigned long, vaddr[1], FIELD_STRING_RETIP, 0);
734 size = SIZEOF_TRACE_ENTRY(true);
735 } else {
736 DEFINE_FIELD(unsigned long, vaddr[0], FIELD_STRING_IP, 0);
737 size = SIZEOF_TRACE_ENTRY(false);
738 }
f3f096cf 739 /* Set argument names as fields */
14577c39
NK
740 for (i = 0; i < tu->tp.nr_args; i++) {
741 struct probe_arg *parg = &tu->tp.args[i];
742
743 ret = trace_define_field(event_call, parg->type->fmttype,
744 parg->name, size + parg->offset,
745 parg->type->size, parg->type->is_signed,
f3f096cf
SD
746 FILTER_OTHER);
747
748 if (ret)
749 return ret;
750 }
751 return 0;
752}
753
f3f096cf 754#ifdef CONFIG_PERF_EVENTS
31ba3348
ON
755static bool
756__uprobe_perf_filter(struct trace_uprobe_filter *filter, struct mm_struct *mm)
757{
758 struct perf_event *event;
759
760 if (filter->nr_systemwide)
761 return true;
762
763 list_for_each_entry(event, &filter->perf_events, hw.tp_list) {
764 if (event->hw.tp_target->mm == mm)
765 return true;
766 }
767
768 return false;
769}
770
b2fe8ba6
ON
771static inline bool
772uprobe_filter_event(struct trace_uprobe *tu, struct perf_event *event)
773{
774 return __uprobe_perf_filter(&tu->filter, event->hw.tp_target->mm);
775}
776
736288ba
ON
777static int uprobe_perf_open(struct trace_uprobe *tu, struct perf_event *event)
778{
b2fe8ba6
ON
779 bool done;
780
736288ba 781 write_lock(&tu->filter.rwlock);
b2fe8ba6
ON
782 if (event->hw.tp_target) {
783 /*
784 * event->parent != NULL means copy_process(), we can avoid
785 * uprobe_apply(). current->mm must be probed and we can rely
786 * on dup_mmap() which preserves the already installed bp's.
787 *
788 * attr.enable_on_exec means that exec/mmap will install the
789 * breakpoints we need.
790 */
791 done = tu->filter.nr_systemwide ||
792 event->parent || event->attr.enable_on_exec ||
793 uprobe_filter_event(tu, event);
736288ba 794 list_add(&event->hw.tp_list, &tu->filter.perf_events);
b2fe8ba6
ON
795 } else {
796 done = tu->filter.nr_systemwide;
736288ba 797 tu->filter.nr_systemwide++;
b2fe8ba6 798 }
736288ba
ON
799 write_unlock(&tu->filter.rwlock);
800
b2fe8ba6
ON
801 if (!done)
802 uprobe_apply(tu->inode, tu->offset, &tu->consumer, true);
31ba3348 803
736288ba
ON
804 return 0;
805}
806
807static int uprobe_perf_close(struct trace_uprobe *tu, struct perf_event *event)
808{
b2fe8ba6
ON
809 bool done;
810
736288ba 811 write_lock(&tu->filter.rwlock);
b2fe8ba6 812 if (event->hw.tp_target) {
736288ba 813 list_del(&event->hw.tp_list);
b2fe8ba6
ON
814 done = tu->filter.nr_systemwide ||
815 (event->hw.tp_target->flags & PF_EXITING) ||
816 uprobe_filter_event(tu, event);
817 } else {
736288ba 818 tu->filter.nr_systemwide--;
b2fe8ba6
ON
819 done = tu->filter.nr_systemwide;
820 }
736288ba
ON
821 write_unlock(&tu->filter.rwlock);
822
b2fe8ba6
ON
823 if (!done)
824 uprobe_apply(tu->inode, tu->offset, &tu->consumer, false);
31ba3348 825
736288ba
ON
826 return 0;
827}
828
31ba3348
ON
829static bool uprobe_perf_filter(struct uprobe_consumer *uc,
830 enum uprobe_filter_ctx ctx, struct mm_struct *mm)
831{
832 struct trace_uprobe *tu;
833 int ret;
834
835 tu = container_of(uc, struct trace_uprobe, consumer);
836 read_lock(&tu->filter.rwlock);
837 ret = __uprobe_perf_filter(&tu->filter, mm);
838 read_unlock(&tu->filter.rwlock);
839
840 return ret;
841}
842
a51cc604
ON
843static void uprobe_perf_print(struct trace_uprobe *tu,
844 unsigned long func, struct pt_regs *regs)
f3f096cf 845{
14577c39 846 struct ftrace_event_call *call = &tu->tp.call;
f3f096cf
SD
847 struct uprobe_trace_entry_head *entry;
848 struct hlist_head *head;
457d1772
ON
849 void *data;
850 int size, rctx, i;
f3f096cf 851
393a736c 852 size = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
14577c39 853 size = ALIGN(size + tu->tp.size + sizeof(u32), sizeof(u64)) - sizeof(u32);
f3f096cf
SD
854
855 preempt_disable();
515619f2
ON
856 head = this_cpu_ptr(call->perf_events);
857 if (hlist_empty(head))
858 goto out;
859
f3f096cf
SD
860 entry = perf_trace_buf_prepare(size, call->event.type, regs, &rctx);
861 if (!entry)
862 goto out;
863
393a736c
ON
864 if (is_ret_probe(tu)) {
865 entry->vaddr[0] = func;
32520b2c 866 entry->vaddr[1] = instruction_pointer(regs);
393a736c
ON
867 data = DATAOF_TRACE_ENTRY(entry, true);
868 } else {
32520b2c 869 entry->vaddr[0] = instruction_pointer(regs);
393a736c
ON
870 data = DATAOF_TRACE_ENTRY(entry, false);
871 }
872
14577c39
NK
873 for (i = 0; i < tu->tp.nr_args; i++) {
874 struct probe_arg *parg = &tu->tp.args[i];
875
876 call_fetch(&parg->fetch, regs, data + parg->offset);
877 }
f3f096cf 878
32520b2c 879 perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL);
f3f096cf
SD
880 out:
881 preempt_enable();
a51cc604
ON
882}
883
884/* uprobe profile handler */
885static int uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs)
886{
887 if (!uprobe_perf_filter(&tu->consumer, 0, current->mm))
888 return UPROBE_HANDLER_REMOVE;
889
393a736c
ON
890 if (!is_ret_probe(tu))
891 uprobe_perf_print(tu, 0, regs);
f42d24a1 892 return 0;
f3f096cf 893}
c1ae5c75
ON
894
895static void uretprobe_perf_func(struct trace_uprobe *tu, unsigned long func,
896 struct pt_regs *regs)
897{
898 uprobe_perf_print(tu, func, regs);
899}
f3f096cf
SD
900#endif /* CONFIG_PERF_EVENTS */
901
902static
903int trace_uprobe_register(struct ftrace_event_call *event, enum trace_reg type, void *data)
904{
457d1772 905 struct trace_uprobe *tu = event->data;
f3f096cf
SD
906
907 switch (type) {
908 case TRACE_REG_REGISTER:
31ba3348 909 return probe_event_enable(tu, TP_FLAG_TRACE, NULL);
f3f096cf
SD
910
911 case TRACE_REG_UNREGISTER:
912 probe_event_disable(tu, TP_FLAG_TRACE);
913 return 0;
914
915#ifdef CONFIG_PERF_EVENTS
916 case TRACE_REG_PERF_REGISTER:
31ba3348 917 return probe_event_enable(tu, TP_FLAG_PROFILE, uprobe_perf_filter);
f3f096cf
SD
918
919 case TRACE_REG_PERF_UNREGISTER:
920 probe_event_disable(tu, TP_FLAG_PROFILE);
921 return 0;
736288ba
ON
922
923 case TRACE_REG_PERF_OPEN:
924 return uprobe_perf_open(tu, data);
925
926 case TRACE_REG_PERF_CLOSE:
927 return uprobe_perf_close(tu, data);
928
f3f096cf
SD
929#endif
930 default:
931 return 0;
932 }
933 return 0;
934}
935
936static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
937{
f3f096cf 938 struct trace_uprobe *tu;
f42d24a1 939 int ret = 0;
f3f096cf 940
a932b738 941 tu = container_of(con, struct trace_uprobe, consumer);
1b47aefd 942 tu->nhit++;
f3f096cf 943
14577c39 944 if (tu->tp.flags & TP_FLAG_TRACE)
f42d24a1 945 ret |= uprobe_trace_func(tu, regs);
f3f096cf
SD
946
947#ifdef CONFIG_PERF_EVENTS
14577c39 948 if (tu->tp.flags & TP_FLAG_PROFILE)
f42d24a1 949 ret |= uprobe_perf_func(tu, regs);
f3f096cf 950#endif
f42d24a1 951 return ret;
f3f096cf
SD
952}
953
c1ae5c75
ON
954static int uretprobe_dispatcher(struct uprobe_consumer *con,
955 unsigned long func, struct pt_regs *regs)
956{
957 struct trace_uprobe *tu;
958
959 tu = container_of(con, struct trace_uprobe, consumer);
960
14577c39 961 if (tu->tp.flags & TP_FLAG_TRACE)
c1ae5c75
ON
962 uretprobe_trace_func(tu, func, regs);
963
964#ifdef CONFIG_PERF_EVENTS
14577c39 965 if (tu->tp.flags & TP_FLAG_PROFILE)
c1ae5c75
ON
966 uretprobe_perf_func(tu, func, regs);
967#endif
968 return 0;
969}
970
f3f096cf
SD
971static struct trace_event_functions uprobe_funcs = {
972 .trace = print_uprobe_event
973};
974
975static int register_uprobe_event(struct trace_uprobe *tu)
976{
14577c39 977 struct ftrace_event_call *call = &tu->tp.call;
f3f096cf
SD
978 int ret;
979
980 /* Initialize ftrace_event_call */
981 INIT_LIST_HEAD(&call->class->fields);
982 call->event.funcs = &uprobe_funcs;
983 call->class->define_fields = uprobe_event_define_fields;
984
5bf652aa 985 if (set_print_fmt(&tu->tp, is_ret_probe(tu)) < 0)
f3f096cf
SD
986 return -ENOMEM;
987
988 ret = register_ftrace_event(&call->event);
989 if (!ret) {
990 kfree(call->print_fmt);
991 return -ENODEV;
992 }
993 call->flags = 0;
994 call->class->reg = trace_uprobe_register;
995 call->data = tu;
996 ret = trace_add_event_call(call);
997
998 if (ret) {
999 pr_info("Failed to register uprobe event: %s\n", call->name);
1000 kfree(call->print_fmt);
1001 unregister_ftrace_event(&call->event);
1002 }
1003
1004 return ret;
1005}
1006
c6c2401d 1007static int unregister_uprobe_event(struct trace_uprobe *tu)
f3f096cf 1008{
c6c2401d
SRRH
1009 int ret;
1010
f3f096cf 1011 /* tu->event is unregistered in trace_remove_event_call() */
14577c39 1012 ret = trace_remove_event_call(&tu->tp.call);
c6c2401d
SRRH
1013 if (ret)
1014 return ret;
14577c39
NK
1015 kfree(tu->tp.call.print_fmt);
1016 tu->tp.call.print_fmt = NULL;
c6c2401d 1017 return 0;
f3f096cf
SD
1018}
1019
1020/* Make a trace interface for controling probe points */
1021static __init int init_uprobe_trace(void)
1022{
1023 struct dentry *d_tracer;
1024
1025 d_tracer = tracing_init_dentry();
1026 if (!d_tracer)
1027 return 0;
1028
1029 trace_create_file("uprobe_events", 0644, d_tracer,
1030 NULL, &uprobe_events_ops);
1031 /* Profile interface */
1032 trace_create_file("uprobe_profile", 0444, d_tracer,
1033 NULL, &uprobe_profile_ops);
1034 return 0;
1035}
1036
1037fs_initcall(init_uprobe_trace);
This page took 0.158769 seconds and 5 git commands to generate.