Blacklist: kprobe for arm
[lttng-modules.git] / probes / lttng-kretprobes.c
CommitLineData
7371f44c 1/*
ccecf3fb 2* probes/lttng-kretprobes.c
7371f44c
MD
3 *
4 * LTTng kretprobes integration module.
5 *
886d51a3
MD
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
7371f44c
MD
21 */
22
23#include <linux/module.h>
24#include <linux/kprobes.h>
25#include <linux/slab.h>
26#include <linux/kref.h>
156a3977
MD
27#include <lttng-events.h>
28#include <wrapper/ringbuffer/frontend_types.h>
29#include <wrapper/vmalloc.h>
30#include <wrapper/irqflags.h>
31#include <lttng-tracer.h>
2d16de12 32#include <blacklist/kprobes.h>
7371f44c
MD
33
34enum lttng_kretprobe_type {
35 EVENT_ENTRY = 0,
36 EVENT_RETURN = 1,
37};
38
39struct lttng_krp {
40 struct kretprobe krp;
a90917c3 41 struct lttng_event *event[2]; /* ENTRY and RETURN */
7371f44c
MD
42 struct kref kref_register;
43 struct kref kref_alloc;
44};
45
46static
47int _lttng_kretprobes_handler(struct kretprobe_instance *krpi,
48 struct pt_regs *regs,
49 enum lttng_kretprobe_type type)
50{
51 struct lttng_krp *lttng_krp =
52 container_of(krpi->rp, struct lttng_krp, krp);
a90917c3 53 struct lttng_event *event =
7371f44c 54 lttng_krp->event[type];
79150a49
JD
55 struct lttng_probe_ctx lttng_probe_ctx = {
56 .event = event,
ccecf3fb 57 .interruptible = !lttng_regs_irqs_disabled(regs),
79150a49 58 };
a90917c3 59 struct lttng_channel *chan = event->chan;
7371f44c
MD
60 struct lib_ring_buffer_ctx ctx;
61 int ret;
62 struct {
63 unsigned long ip;
64 unsigned long parent_ip;
65 } payload;
66
acb98454 67 if (unlikely(!READ_ONCE(chan->session->active)))
7371f44c 68 return 0;
acb98454 69 if (unlikely(!READ_ONCE(chan->enabled)))
7371f44c 70 return 0;
acb98454 71 if (unlikely(!READ_ONCE(event->enabled)))
7371f44c
MD
72 return 0;
73
74 payload.ip = (unsigned long) krpi->rp->kp.addr;
75 payload.parent_ip = (unsigned long) krpi->ret_addr;
76
79150a49 77 lib_ring_buffer_ctx_init(&ctx, chan->chan, &lttng_probe_ctx, sizeof(payload),
a90917c3 78 lttng_alignof(payload), -1);
7371f44c
MD
79 ret = chan->ops->event_reserve(&ctx, event->id);
80 if (ret < 0)
81 return 0;
a90917c3 82 lib_ring_buffer_align_ctx(&ctx, lttng_alignof(payload));
7371f44c
MD
83 chan->ops->event_write(&ctx, &payload, sizeof(payload));
84 chan->ops->event_commit(&ctx);
85 return 0;
86}
87
88static
89int lttng_kretprobes_handler_entry(struct kretprobe_instance *krpi,
90 struct pt_regs *regs)
91{
92 return _lttng_kretprobes_handler(krpi, regs, EVENT_ENTRY);
93}
94
95static
96int lttng_kretprobes_handler_return(struct kretprobe_instance *krpi,
97 struct pt_regs *regs)
98{
99 return _lttng_kretprobes_handler(krpi, regs, EVENT_RETURN);
100}
101
102/*
103 * Create event description
104 */
105static
a90917c3 106int lttng_create_kprobe_event(const char *name, struct lttng_event *event,
7371f44c
MD
107 enum lttng_kretprobe_type type)
108{
109 struct lttng_event_field *fields;
110 struct lttng_event_desc *desc;
111 int ret;
112 char *alloc_name;
113 size_t name_len;
114 const char *suffix = NULL;
115
116 desc = kzalloc(sizeof(*event->desc), GFP_KERNEL);
117 if (!desc)
118 return -ENOMEM;
119 name_len = strlen(name);
120 switch (type) {
121 case EVENT_ENTRY:
122 suffix = "_entry";
123 break;
124 case EVENT_RETURN:
125 suffix = "_return";
126 break;
127 }
128 name_len += strlen(suffix);
129 alloc_name = kmalloc(name_len + 1, GFP_KERNEL);
130 if (!alloc_name) {
131 ret = -ENOMEM;
132 goto error_str;
133 }
134 strcpy(alloc_name, name);
135 strcat(alloc_name, suffix);
136 desc->name = alloc_name;
137 desc->nr_fields = 2;
138 desc->fields = fields =
139 kzalloc(2 * sizeof(struct lttng_event_field), GFP_KERNEL);
140 if (!desc->fields) {
141 ret = -ENOMEM;
142 goto error_fields;
143 }
144 fields[0].name = "ip";
145 fields[0].type.atype = atype_integer;
146 fields[0].type.u.basic.integer.size = sizeof(unsigned long) * CHAR_BIT;
a90917c3 147 fields[0].type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT;
06254b0f 148 fields[0].type.u.basic.integer.signedness = lttng_is_signed_type(unsigned long);
7371f44c
MD
149 fields[0].type.u.basic.integer.reverse_byte_order = 0;
150 fields[0].type.u.basic.integer.base = 16;
151 fields[0].type.u.basic.integer.encoding = lttng_encode_none;
152
153 fields[1].name = "parent_ip";
154 fields[1].type.atype = atype_integer;
155 fields[1].type.u.basic.integer.size = sizeof(unsigned long) * CHAR_BIT;
a90917c3 156 fields[1].type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT;
06254b0f 157 fields[1].type.u.basic.integer.signedness = lttng_is_signed_type(unsigned long);
7371f44c
MD
158 fields[1].type.u.basic.integer.reverse_byte_order = 0;
159 fields[1].type.u.basic.integer.base = 16;
160 fields[1].type.u.basic.integer.encoding = lttng_encode_none;
161
162 desc->owner = THIS_MODULE;
163 event->desc = desc;
164
165 return 0;
166
167error_fields:
168 kfree(desc->name);
169error_str:
170 kfree(desc);
171 return ret;
172}
173
174int lttng_kretprobes_register(const char *name,
175 const char *symbol_name,
176 uint64_t offset,
177 uint64_t addr,
a90917c3
MD
178 struct lttng_event *event_entry,
179 struct lttng_event *event_return)
7371f44c
MD
180{
181 int ret;
182 struct lttng_krp *lttng_krp;
183
184 /* Kprobes expects a NULL symbol name if unused */
185 if (symbol_name[0] == '\0')
186 symbol_name = NULL;
187
188 ret = lttng_create_kprobe_event(name, event_entry, EVENT_ENTRY);
189 if (ret)
190 goto error;
191 ret = lttng_create_kprobe_event(name, event_return, EVENT_RETURN);
192 if (ret)
193 goto event_return_error;
194 lttng_krp = kzalloc(sizeof(*lttng_krp), GFP_KERNEL);
195 if (!lttng_krp)
196 goto krp_error;
197 lttng_krp->krp.entry_handler = lttng_kretprobes_handler_entry;
198 lttng_krp->krp.handler = lttng_kretprobes_handler_return;
199 if (symbol_name) {
200 char *alloc_symbol;
201
202 alloc_symbol = kstrdup(symbol_name, GFP_KERNEL);
203 if (!alloc_symbol) {
204 ret = -ENOMEM;
205 goto name_error;
206 }
207 lttng_krp->krp.kp.symbol_name =
208 alloc_symbol;
209 event_entry->u.kretprobe.symbol_name =
210 alloc_symbol;
211 event_return->u.kretprobe.symbol_name =
212 alloc_symbol;
213 }
214 lttng_krp->krp.kp.offset = offset;
b2c4e8fb 215 lttng_krp->krp.kp.addr = (void *) (unsigned long) addr;
7371f44c
MD
216
217 /* Allow probe handler to find event structures */
218 lttng_krp->event[EVENT_ENTRY] = event_entry;
219 lttng_krp->event[EVENT_RETURN] = event_return;
220 event_entry->u.kretprobe.lttng_krp = lttng_krp;
221 event_return->u.kretprobe.lttng_krp = lttng_krp;
222
223 /*
224 * Both events must be unregistered before the kretprobe is
225 * unregistered. Same for memory allocation.
226 */
227 kref_init(&lttng_krp->kref_alloc);
9c1f4643 228 kref_get(&lttng_krp->kref_alloc); /* inc refcount to 2, no overflow. */
7371f44c 229 kref_init(&lttng_krp->kref_register);
9c1f4643 230 kref_get(&lttng_krp->kref_register); /* inc refcount to 2, no overflow. */
7371f44c
MD
231
232 /*
233 * Ensure the memory we just allocated don't trigger page faults.
234 * Well.. kprobes itself puts the page fault handler on the blacklist,
235 * but we can never be too careful.
236 */
237 wrapper_vmalloc_sync_all();
238
239 ret = register_kretprobe(&lttng_krp->krp);
240 if (ret)
241 goto register_error;
242 return 0;
243
244register_error:
245 kfree(lttng_krp->krp.kp.symbol_name);
246name_error:
247 kfree(lttng_krp);
248krp_error:
249 kfree(event_return->desc->fields);
250 kfree(event_return->desc->name);
251 kfree(event_return->desc);
252event_return_error:
253 kfree(event_entry->desc->fields);
254 kfree(event_entry->desc->name);
255 kfree(event_entry->desc);
256error:
257 return ret;
258}
259EXPORT_SYMBOL_GPL(lttng_kretprobes_register);
260
261static
262void _lttng_kretprobes_unregister_release(struct kref *kref)
263{
264 struct lttng_krp *lttng_krp =
265 container_of(kref, struct lttng_krp, kref_register);
266 unregister_kretprobe(&lttng_krp->krp);
267}
268
a90917c3 269void lttng_kretprobes_unregister(struct lttng_event *event)
7371f44c
MD
270{
271 kref_put(&event->u.kretprobe.lttng_krp->kref_register,
272 _lttng_kretprobes_unregister_release);
273}
274EXPORT_SYMBOL_GPL(lttng_kretprobes_unregister);
275
276static
277void _lttng_kretprobes_release(struct kref *kref)
278{
279 struct lttng_krp *lttng_krp =
280 container_of(kref, struct lttng_krp, kref_alloc);
281 kfree(lttng_krp->krp.kp.symbol_name);
282}
283
a90917c3 284void lttng_kretprobes_destroy_private(struct lttng_event *event)
7371f44c
MD
285{
286 kfree(event->desc->fields);
287 kfree(event->desc->name);
288 kfree(event->desc);
289 kref_put(&event->u.kretprobe.lttng_krp->kref_alloc,
290 _lttng_kretprobes_release);
291}
292EXPORT_SYMBOL_GPL(lttng_kretprobes_destroy_private);
293
a0493bef
MD
294int lttng_kretprobes_event_enable_state(struct lttng_event *event,
295 int enable)
296{
297 struct lttng_event *event_return;
298 struct lttng_krp *lttng_krp;
299
300 if (event->instrumentation != LTTNG_KERNEL_KRETPROBE) {
301 return -EINVAL;
302 }
303 if (event->enabled == enable) {
304 return -EBUSY;
305 }
306 lttng_krp = event->u.kretprobe.lttng_krp;
307 event_return = lttng_krp->event[EVENT_RETURN];
acb98454
MJ
308 WRITE_ONCE(event->enabled, enable);
309 WRITE_ONCE(event_return->enabled, enable);
a0493bef
MD
310 return 0;
311}
312EXPORT_SYMBOL_GPL(lttng_kretprobes_event_enable_state);
313
7371f44c
MD
314MODULE_LICENSE("GPL and additional rights");
315MODULE_AUTHOR("Mathieu Desnoyers");
316MODULE_DESCRIPTION("Linux Trace Toolkit Kretprobes Support");
13ab8b0a
MD
317MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
318 __stringify(LTTNG_MODULES_MINOR_VERSION) "."
319 __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
320 LTTNG_MODULES_EXTRAVERSION);
This page took 0.04785 seconds and 4 git commands to generate.