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