Refactoring: event structures
[lttng-modules.git] / src / probes / lttng-uprobes.c
CommitLineData
b7cdc182 1/* SPDX-License-Identifier: (GPL-2.0-only OR LGPL-2.1-only)
8134eb60 2 *
149b9a9d
YB
3 * probes/lttng-uprobes.c
4 *
5 * LTTng uprobes integration module.
6 *
7 * Copyright (C) 2013 Yannick Brosseau <yannick.brosseau@gmail.com>
8 * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 *
149b9a9d
YB
10 */
11
0aebcd68 12#include <wrapper/fdtable.h>
3aed4dca 13#include <linux/list.h>
149b9a9d
YB
14#include <linux/module.h>
15#include <linux/namei.h>
16#include <linux/slab.h>
3aed4dca 17#include <linux/uaccess.h>
2df37e95 18#include <lttng/events.h>
a67ba386 19#include <lttng/events-internal.h>
2df37e95 20#include <lttng/tracer.h>
149b9a9d 21#include <wrapper/irqflags.h>
24591303 22#include <ringbuffer/frontend_types.h>
149b9a9d
YB
23#include <wrapper/uprobes.h>
24#include <wrapper/vmalloc.h>
25
26static
83b802dc 27int lttng_uprobes_event_handler_pre(struct uprobe_consumer *uc, struct pt_regs *regs)
149b9a9d 28{
3aed4dca
FD
29 struct lttng_uprobe_handler *uprobe_handler =
30 container_of(uc, struct lttng_uprobe_handler, up_consumer);
a67ba386 31 struct lttng_kernel_event_recorder *event_recorder = uprobe_handler->u.event;
149b9a9d 32 struct lttng_probe_ctx lttng_probe_ctx = {
a67ba386 33 .event = event_recorder,
149b9a9d
YB
34 .interruptible = !lttng_regs_irqs_disabled(regs),
35 };
a67ba386 36 struct lttng_channel *chan = event_recorder->chan;
149b9a9d
YB
37 struct lib_ring_buffer_ctx ctx;
38 int ret;
39
40 struct {
41 unsigned long ip;
56377c91 42 } payload;
149b9a9d 43
585e5dcc 44 if (unlikely(!LTTNG_READ_ONCE(chan->session->active)))
149b9a9d 45 return 0;
585e5dcc 46 if (unlikely(!LTTNG_READ_ONCE(chan->enabled)))
149b9a9d 47 return 0;
a67ba386 48 if (unlikely(!LTTNG_READ_ONCE(event_recorder->parent.enabled)))
149b9a9d
YB
49 return 0;
50
51 lib_ring_buffer_ctx_init(&ctx, chan->chan, &lttng_probe_ctx,
52 sizeof(payload), lttng_alignof(payload), -1);
53
a67ba386 54 ret = chan->ops->event_reserve(&ctx, event_recorder->priv->id);
149b9a9d
YB
55 if (ret < 0)
56 return 0;
57
58 /* Event payload. */
7445d54f 59 payload.ip = (unsigned long)instruction_pointer(regs);
56377c91 60
149b9a9d
YB
61 lib_ring_buffer_align_ctx(&ctx, lttng_alignof(payload));
62 chan->ops->event_write(&ctx, &payload, sizeof(payload));
63 chan->ops->event_commit(&ctx);
64 return 0;
65}
66
9de67196
FD
67static
68int lttng_uprobes_event_notifier_handler_pre(struct uprobe_consumer *uc, struct pt_regs *regs)
69{
70 struct lttng_uprobe_handler *uprobe_handler =
71 container_of(uc, struct lttng_uprobe_handler, up_consumer);
a67ba386
MD
72 struct lttng_kernel_event_notifier *event_notifier = uprobe_handler->u.event_notifier;
73 struct lttng_kernel_notification_ctx notif_ctx;
9de67196 74
a67ba386 75 if (unlikely(!READ_ONCE(event_notifier->parent.enabled)))
9de67196
FD
76 return 0;
77
c3eddb2e 78 notif_ctx.eval_capture = LTTNG_READ_ONCE(event_notifier->eval_capture);
a67ba386 79 event_notifier->notification_send(event_notifier, NULL, NULL, &notif_ctx);
9de67196
FD
80 return 0;
81}
82
437d5aa5
MD
83static const struct lttng_kernel_type_common *event_type =
84 lttng_kernel_static_type_integer_from_type(unsigned long, __BYTE_ORDER, 16);
85
149b9a9d
YB
86/*
87 * Create event description.
88 */
89static
a67ba386 90int lttng_create_uprobe_event(const char *name, struct lttng_kernel_event_recorder *event_recorder)
149b9a9d 91{
437d5aa5
MD
92 const struct lttng_kernel_event_field **fieldp_array;
93 struct lttng_kernel_event_field *field;
94 struct lttng_kernel_event_desc *desc;
149b9a9d
YB
95 int ret;
96
437d5aa5 97 desc = kzalloc(sizeof(*desc), GFP_KERNEL);
149b9a9d
YB
98 if (!desc)
99 return -ENOMEM;
437d5aa5
MD
100 desc->event_name = kstrdup(name, GFP_KERNEL);
101 if (!desc->event_name) {
149b9a9d
YB
102 ret = -ENOMEM;
103 goto error_str;
104 }
149b9a9d 105 desc->nr_fields = 1;
437d5aa5
MD
106 fieldp_array = kzalloc(1 * sizeof(struct lttng_kernel_event_field *), GFP_KERNEL);
107 if (!fieldp_array) {
149b9a9d 108 ret = -ENOMEM;
437d5aa5 109 goto error_fieldp_array;
149b9a9d 110 }
437d5aa5
MD
111 desc->fields = fieldp_array;
112 desc->fields[0] = field =
113 kzalloc(sizeof(struct lttng_kernel_event_field), GFP_KERNEL);
114 if (!field) {
115 ret = -ENOMEM;
116 goto error_field;
117 }
118 field->name = "ip";
119 field->type = event_type;
149b9a9d 120 desc->owner = THIS_MODULE;
a67ba386 121 event_recorder->priv->parent.desc = desc;
149b9a9d
YB
122
123 return 0;
124
437d5aa5
MD
125error_field:
126 kfree(fieldp_array);
127error_fieldp_array:
128 kfree(desc->event_name);
149b9a9d
YB
129error_str:
130 kfree(desc);
131 return ret;
132}
133
9de67196
FD
134/*
135 * Create event_notifier description.
136 */
137static
a67ba386 138int lttng_create_uprobe_event_notifier(const char *name, struct lttng_kernel_event_notifier *event_notifier)
9de67196 139{
437d5aa5 140 struct lttng_kernel_event_desc *desc;
9de67196
FD
141 int ret;
142
437d5aa5 143 desc = kzalloc(sizeof(*desc), GFP_KERNEL);
9de67196
FD
144 if (!desc)
145 return -ENOMEM;
437d5aa5
MD
146 desc->event_name = kstrdup(name, GFP_KERNEL);
147 if (!desc->event_name) {
9de67196
FD
148 ret = -ENOMEM;
149 goto error_str;
150 }
151
152 desc->nr_fields = 0;
153
154 desc->owner = THIS_MODULE;
a67ba386 155 event_notifier->priv->parent.desc = desc;
9de67196
FD
156
157 return 0;
158
159error_str:
160 kfree(desc);
161 return ret;
162}
163
56377c91
FD
164/*
165 * Returns the inode struct from the current task and an fd. The inode is
166 * grabbed by this function and must be put once we are done with it using
167 * iput().
168 */
169static struct inode *get_inode_from_fd(int fd)
170{
171 struct file *file;
172 struct inode *inode;
173
174 rcu_read_lock();
175 /*
176 * Returns the file backing the given fd. Needs to be done inside an RCU
177 * critical section.
178 */
0aebcd68 179 file = lttng_lookup_fd_rcu(fd);
56377c91 180 if (file == NULL) {
5a15f70c 181 printk(KERN_WARNING "LTTng: Cannot access file backing the fd(%d)\n", fd);
56377c91
FD
182 inode = NULL;
183 goto error;
184 }
185
186 /* Grab a reference on the inode. */
187 inode = igrab(file->f_path.dentry->d_inode);
188 if (inode == NULL)
5a15f70c 189 printk(KERN_WARNING "LTTng: Cannot grab a reference on the inode.\n");
56377c91
FD
190error:
191 rcu_read_unlock();
192 return inode;
193}
194
83b802dc
FD
195
196static
197int lttng_uprobes_add_callsite(struct lttng_uprobe *uprobe,
606828e4 198 struct lttng_kernel_abi_event_callsite __user *callsite,
83b802dc
FD
199 int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs),
200 void *priv_data)
149b9a9d 201{
3aed4dca
FD
202 int ret = 0;
203 struct lttng_uprobe_handler *uprobe_handler;
204
83b802dc 205 if (!priv_data) {
3aed4dca
FD
206 ret = -EINVAL;
207 goto end;
208 }
209
210 uprobe_handler = kzalloc(sizeof(struct lttng_uprobe_handler), GFP_KERNEL);
211 if (!uprobe_handler) {
5a15f70c 212 printk(KERN_WARNING "LTTng: Error allocating uprobe_handler");
3aed4dca
FD
213 ret = -ENOMEM;
214 goto end;
215 }
216
196bfc6a 217 /* Ensure the memory we just allocated don't notify page faults. */
263b6c88 218 wrapper_vmalloc_sync_mappings();
3aed4dca 219
83b802dc
FD
220 uprobe_handler->u.event = priv_data;
221 uprobe_handler->up_consumer.handler = handler;
3aed4dca
FD
222
223 ret = copy_from_user(&uprobe_handler->offset, &callsite->u.uprobe.offset, sizeof(uint64_t));
224 if (ret) {
225 goto register_error;
226 }
227
83b802dc 228 ret = wrapper_uprobe_register(uprobe->inode,
3aed4dca
FD
229 uprobe_handler->offset, &uprobe_handler->up_consumer);
230 if (ret) {
5a15f70c 231 printk(KERN_WARNING "LTTng: Error registering probe on inode %lu "
83b802dc 232 "and offset 0x%llx\n", uprobe->inode->i_ino,
3aed4dca
FD
233 uprobe_handler->offset);
234 ret = -1;
235 goto register_error;
236 }
237
83b802dc 238 list_add(&uprobe_handler->node, &uprobe->head);
3aed4dca
FD
239
240 return ret;
241
242register_error:
243 kfree(uprobe_handler);
244end:
245 return ret;
246}
3aed4dca 247
a67ba386 248int lttng_uprobes_event_add_callsite(struct lttng_kernel_event_recorder *event_recorder,
606828e4 249 struct lttng_kernel_abi_event_callsite __user *callsite)
83b802dc 250{
a67ba386
MD
251 return lttng_uprobes_add_callsite(&event_recorder->priv->parent.u.uprobe, callsite,
252 lttng_uprobes_event_handler_pre, event_recorder);
83b802dc
FD
253}
254EXPORT_SYMBOL_GPL(lttng_uprobes_event_add_callsite);
255
a67ba386 256int lttng_uprobes_event_notifier_add_callsite(struct lttng_kernel_event_notifier *event_notifier,
606828e4 257 struct lttng_kernel_abi_event_callsite __user *callsite)
9de67196 258{
a67ba386 259 return lttng_uprobes_add_callsite(&event_notifier->priv->parent.u.uprobe, callsite,
9de67196
FD
260 lttng_uprobes_event_notifier_handler_pre, event_notifier);
261}
262EXPORT_SYMBOL_GPL(lttng_uprobes_event_notifier_add_callsite);
263
83b802dc
FD
264static
265int lttng_uprobes_register(struct lttng_uprobe *uprobe, int fd)
3aed4dca
FD
266{
267 int ret = 0;
56377c91 268 struct inode *inode;
149b9a9d 269
56377c91
FD
270 inode = get_inode_from_fd(fd);
271 if (!inode) {
5a15f70c 272 printk(KERN_WARNING "LTTng: Cannot get inode from fd\n");
56377c91
FD
273 ret = -EBADF;
274 goto inode_error;
275 }
83b802dc
FD
276 uprobe->inode = inode;
277 INIT_LIST_HEAD(&uprobe->head);
278
279inode_error:
280 return ret;
281}
282
a67ba386 283int lttng_uprobes_register_event(const char *name, int fd, struct lttng_kernel_event_recorder *event_recorder)
83b802dc
FD
284{
285 int ret = 0;
286
a67ba386 287 ret = lttng_create_uprobe_event(name, event_recorder);
83b802dc
FD
288 if (ret)
289 goto error;
290
a67ba386 291 ret = lttng_uprobes_register(&event_recorder->priv->parent.u.uprobe, fd);
83b802dc
FD
292 if (ret)
293 goto register_error;
149b9a9d 294
149b9a9d
YB
295 return 0;
296
83b802dc 297register_error:
a67ba386
MD
298 kfree(event_recorder->priv->parent.desc->event_name);
299 kfree(event_recorder->priv->parent.desc);
149b9a9d
YB
300error:
301 return ret;
302}
83b802dc 303EXPORT_SYMBOL_GPL(lttng_uprobes_register_event);
149b9a9d 304
9de67196 305int lttng_uprobes_register_event_notifier(const char *name, int fd,
a67ba386 306 struct lttng_kernel_event_notifier *event_notifier)
9de67196
FD
307{
308 int ret = 0;
309
310 ret = lttng_create_uprobe_event_notifier(name, event_notifier);
311 if (ret)
312 goto error;
313
a67ba386 314 ret = lttng_uprobes_register(&event_notifier->priv->parent.u.uprobe, fd);
9de67196
FD
315 if (ret)
316 goto register_error;
317
318 return 0;
319
320register_error:
a67ba386
MD
321 kfree(event_notifier->priv->parent.desc->event_name);
322 kfree(event_notifier->priv->parent.desc);
9de67196
FD
323error:
324 return ret;
325}
326EXPORT_SYMBOL_GPL(lttng_uprobes_register_event_notifier);
327
328static
329void lttng_uprobes_unregister(struct inode *inode, struct list_head *head)
149b9a9d 330{
3aed4dca
FD
331 struct lttng_uprobe_handler *iter, *tmp;
332
333 /*
334 * Iterate over the list of handler, remove each handler from the list
335 * and free the struct.
336 */
9de67196
FD
337 list_for_each_entry_safe(iter, tmp, head, node) {
338 wrapper_uprobe_unregister(inode, iter->offset, &iter->up_consumer);
3aed4dca
FD
339 list_del(&iter->node);
340 kfree(iter);
341 }
9de67196
FD
342
343}
344
a67ba386 345void lttng_uprobes_unregister_event(struct lttng_kernel_event_recorder *event_recorder)
9de67196 346{
a67ba386 347 lttng_uprobes_unregister(event_recorder->priv->parent.u.uprobe.inode, &event_recorder->priv->parent.u.uprobe.head);
149b9a9d 348}
83b802dc 349EXPORT_SYMBOL_GPL(lttng_uprobes_unregister_event);
149b9a9d 350
a67ba386 351void lttng_uprobes_unregister_event_notifier(struct lttng_kernel_event_notifier *event_notifier)
9de67196 352{
a67ba386 353 lttng_uprobes_unregister(event_notifier->priv->parent.u.uprobe.inode, &event_notifier->priv->parent.u.uprobe.head);
9de67196
FD
354}
355EXPORT_SYMBOL_GPL(lttng_uprobes_unregister_event_notifier);
356
a67ba386 357void lttng_uprobes_destroy_event_private(struct lttng_kernel_event_recorder *event_recorder)
149b9a9d 358{
a67ba386
MD
359 iput(event_recorder->priv->parent.u.uprobe.inode);
360 kfree(event_recorder->priv->parent.desc->fields[0]);
361 kfree(event_recorder->priv->parent.desc->fields);
362 kfree(event_recorder->priv->parent.desc->event_name);
363 kfree(event_recorder->priv->parent.desc);
149b9a9d 364}
83b802dc 365EXPORT_SYMBOL_GPL(lttng_uprobes_destroy_event_private);
149b9a9d 366
a67ba386 367void lttng_uprobes_destroy_event_notifier_private(struct lttng_kernel_event_notifier *event_notifier)
9de67196 368{
a67ba386
MD
369 iput(event_notifier->priv->parent.u.uprobe.inode);
370 kfree(event_notifier->priv->parent.desc->event_name);
371 kfree(event_notifier->priv->parent.desc);
9de67196
FD
372}
373EXPORT_SYMBOL_GPL(lttng_uprobes_destroy_event_notifier_private);
374
149b9a9d
YB
375MODULE_LICENSE("GPL and additional rights");
376MODULE_AUTHOR("Yannick Brosseau");
377MODULE_DESCRIPTION("Linux Trace Toolkit Uprobes Support");
This page took 0.05608 seconds and 4 git commands to generate.