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