Blacklist: kprobe for arm
[lttng-modules.git] / probes / lttng-kprobes.c
1 /*
2 * probes/lttng-kprobes.c
3 *
4 * LTTng kprobes integration module.
5 *
6 * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <linux/module.h>
24 #include <linux/kprobes.h>
25 #include <linux/slab.h>
26 #include <lttng-events.h>
27 #include <wrapper/ringbuffer/frontend_types.h>
28 #include <wrapper/vmalloc.h>
29 #include <wrapper/irqflags.h>
30 #include <lttng-tracer.h>
31 #include <blacklist/kprobes.h>
32
33 static
34 int lttng_kprobes_handler_pre(struct kprobe *p, struct pt_regs *regs)
35 {
36 struct lttng_event *event =
37 container_of(p, struct lttng_event, u.kprobe.kp);
38 struct lttng_probe_ctx lttng_probe_ctx = {
39 .event = event,
40 .interruptible = !lttng_regs_irqs_disabled(regs),
41 };
42 struct lttng_channel *chan = event->chan;
43 struct lib_ring_buffer_ctx ctx;
44 int ret;
45 unsigned long data = (unsigned long) p->addr;
46
47 if (unlikely(!READ_ONCE(chan->session->active)))
48 return 0;
49 if (unlikely(!READ_ONCE(chan->enabled)))
50 return 0;
51 if (unlikely(!READ_ONCE(event->enabled)))
52 return 0;
53
54 lib_ring_buffer_ctx_init(&ctx, chan->chan, &lttng_probe_ctx, sizeof(data),
55 lttng_alignof(data), -1);
56 ret = chan->ops->event_reserve(&ctx, event->id);
57 if (ret < 0)
58 return 0;
59 lib_ring_buffer_align_ctx(&ctx, lttng_alignof(data));
60 chan->ops->event_write(&ctx, &data, sizeof(data));
61 chan->ops->event_commit(&ctx);
62 return 0;
63 }
64
65 /*
66 * Create event description
67 */
68 static
69 int lttng_create_kprobe_event(const char *name, struct lttng_event *event)
70 {
71 struct lttng_event_field *field;
72 struct lttng_event_desc *desc;
73 int ret;
74
75 desc = kzalloc(sizeof(*event->desc), GFP_KERNEL);
76 if (!desc)
77 return -ENOMEM;
78 desc->name = kstrdup(name, GFP_KERNEL);
79 if (!desc->name) {
80 ret = -ENOMEM;
81 goto error_str;
82 }
83 desc->nr_fields = 1;
84 desc->fields = field =
85 kzalloc(1 * sizeof(struct lttng_event_field), GFP_KERNEL);
86 if (!field) {
87 ret = -ENOMEM;
88 goto error_field;
89 }
90 field->name = "ip";
91 field->type.atype = atype_integer;
92 field->type.u.basic.integer.size = sizeof(unsigned long) * CHAR_BIT;
93 field->type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT;
94 field->type.u.basic.integer.signedness = lttng_is_signed_type(unsigned long);
95 field->type.u.basic.integer.reverse_byte_order = 0;
96 field->type.u.basic.integer.base = 16;
97 field->type.u.basic.integer.encoding = lttng_encode_none;
98 desc->owner = THIS_MODULE;
99 event->desc = desc;
100
101 return 0;
102
103 error_field:
104 kfree(desc->name);
105 error_str:
106 kfree(desc);
107 return ret;
108 }
109
110 int lttng_kprobes_register(const char *name,
111 const char *symbol_name,
112 uint64_t offset,
113 uint64_t addr,
114 struct lttng_event *event)
115 {
116 int ret;
117
118 /* Kprobes expects a NULL symbol name if unused */
119 if (symbol_name[0] == '\0')
120 symbol_name = NULL;
121
122 ret = lttng_create_kprobe_event(name, event);
123 if (ret)
124 goto error;
125 memset(&event->u.kprobe.kp, 0, sizeof(event->u.kprobe.kp));
126 event->u.kprobe.kp.pre_handler = lttng_kprobes_handler_pre;
127 if (symbol_name) {
128 event->u.kprobe.symbol_name =
129 kzalloc(LTTNG_KERNEL_SYM_NAME_LEN * sizeof(char),
130 GFP_KERNEL);
131 if (!event->u.kprobe.symbol_name) {
132 ret = -ENOMEM;
133 goto name_error;
134 }
135 memcpy(event->u.kprobe.symbol_name, symbol_name,
136 LTTNG_KERNEL_SYM_NAME_LEN * sizeof(char));
137 event->u.kprobe.kp.symbol_name =
138 event->u.kprobe.symbol_name;
139 }
140 event->u.kprobe.kp.offset = offset;
141 event->u.kprobe.kp.addr = (void *) (unsigned long) addr;
142
143 /*
144 * Ensure the memory we just allocated don't trigger page faults.
145 * Well.. kprobes itself puts the page fault handler on the blacklist,
146 * but we can never be too careful.
147 */
148 wrapper_vmalloc_sync_all();
149
150 ret = register_kprobe(&event->u.kprobe.kp);
151 if (ret)
152 goto register_error;
153 return 0;
154
155 register_error:
156 kfree(event->u.kprobe.symbol_name);
157 name_error:
158 kfree(event->desc->fields);
159 kfree(event->desc->name);
160 kfree(event->desc);
161 error:
162 return ret;
163 }
164 EXPORT_SYMBOL_GPL(lttng_kprobes_register);
165
166 void lttng_kprobes_unregister(struct lttng_event *event)
167 {
168 unregister_kprobe(&event->u.kprobe.kp);
169 }
170 EXPORT_SYMBOL_GPL(lttng_kprobes_unregister);
171
172 void lttng_kprobes_destroy_private(struct lttng_event *event)
173 {
174 kfree(event->u.kprobe.symbol_name);
175 kfree(event->desc->fields);
176 kfree(event->desc->name);
177 kfree(event->desc);
178 }
179 EXPORT_SYMBOL_GPL(lttng_kprobes_destroy_private);
180
181 MODULE_LICENSE("GPL and additional rights");
182 MODULE_AUTHOR("Mathieu Desnoyers");
183 MODULE_DESCRIPTION("Linux Trace Toolkit Kprobes Support");
184 MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
185 __stringify(LTTNG_MODULES_MINOR_VERSION) "."
186 __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
187 LTTNG_MODULES_EXTRAVERSION);
This page took 0.035644 seconds and 4 git commands to generate.