workqueue instrumentation: remove duplicated structures
[deliverable/lttng-modules.git] / probes / lttng-kretprobes.c
1 /*
2 * probes/lttng-kretprobes.c
3 *
4 * LTTng kretprobes 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 <linux/kref.h>
27 #include "../lttng-events.h"
28 #include "../wrapper/ringbuffer/frontend_types.h"
29 #include "../wrapper/vmalloc.h"
30 #include "../lttng-tracer.h"
31
32 enum lttng_kretprobe_type {
33 EVENT_ENTRY = 0,
34 EVENT_RETURN = 1,
35 };
36
37 struct lttng_krp {
38 struct kretprobe krp;
39 struct lttng_event *event[2]; /* ENTRY and RETURN */
40 struct kref kref_register;
41 struct kref kref_alloc;
42 };
43
44 static
45 int _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);
51 struct lttng_event *event =
52 lttng_krp->event[type];
53 struct lttng_channel *chan = event->chan;
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),
72 lttng_alignof(payload), -1);
73 ret = chan->ops->event_reserve(&ctx, event->id);
74 if (ret < 0)
75 return 0;
76 lib_ring_buffer_align_ctx(&ctx, lttng_alignof(payload));
77 chan->ops->event_write(&ctx, &payload, sizeof(payload));
78 chan->ops->event_commit(&ctx);
79 return 0;
80 }
81
82 static
83 int 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
89 static
90 int 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 */
99 static
100 int lttng_create_kprobe_event(const char *name, struct lttng_event *event,
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;
141 fields[0].type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT;
142 fields[0].type.u.basic.integer.signedness = lttng_is_signed_type(unsigned long);
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;
150 fields[1].type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT;
151 fields[1].type.u.basic.integer.signedness = lttng_is_signed_type(unsigned long);
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
161 error_fields:
162 kfree(desc->name);
163 error_str:
164 kfree(desc);
165 return ret;
166 }
167
168 int lttng_kretprobes_register(const char *name,
169 const char *symbol_name,
170 uint64_t offset,
171 uint64_t addr,
172 struct lttng_event *event_entry,
173 struct lttng_event *event_return)
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;
209 lttng_krp->krp.kp.addr = (void *) (unsigned long) addr;
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
238 register_error:
239 kfree(lttng_krp->krp.kp.symbol_name);
240 name_error:
241 kfree(lttng_krp);
242 krp_error:
243 kfree(event_return->desc->fields);
244 kfree(event_return->desc->name);
245 kfree(event_return->desc);
246 event_return_error:
247 kfree(event_entry->desc->fields);
248 kfree(event_entry->desc->name);
249 kfree(event_entry->desc);
250 error:
251 return ret;
252 }
253 EXPORT_SYMBOL_GPL(lttng_kretprobes_register);
254
255 static
256 void _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
263 void lttng_kretprobes_unregister(struct lttng_event *event)
264 {
265 kref_put(&event->u.kretprobe.lttng_krp->kref_register,
266 _lttng_kretprobes_unregister_release);
267 }
268 EXPORT_SYMBOL_GPL(lttng_kretprobes_unregister);
269
270 static
271 void _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
278 void lttng_kretprobes_destroy_private(struct lttng_event *event)
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 }
286 EXPORT_SYMBOL_GPL(lttng_kretprobes_destroy_private);
287
288 MODULE_LICENSE("GPL and additional rights");
289 MODULE_AUTHOR("Mathieu Desnoyers");
290 MODULE_DESCRIPTION("Linux Trace Toolkit Kretprobes Support");
This page took 0.036317 seconds and 5 git commands to generate.