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