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