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