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