Cleanup: namespace string encoding
[lttng-modules.git] / src / probes / lttng-kprobes.c
CommitLineData
b7cdc182 1/* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
9f36eaed 2 *
886d51a3 3 * probes/lttng-kprobes.c
d6d808f3
MD
4 *
5 * LTTng kprobes integration module.
6 *
886d51a3 7 * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
d6d808f3
MD
8 */
9
10#include <linux/module.h>
11#include <linux/kprobes.h>
f17701fb 12#include <linux/slab.h>
2df37e95 13#include <lttng/events.h>
24591303 14#include <ringbuffer/frontend_types.h>
156a3977
MD
15#include <wrapper/vmalloc.h>
16#include <wrapper/irqflags.h>
2df37e95 17#include <lttng/tracer.h>
caa068b5 18#include <blacklist/kprobes.h>
d6d808f3 19
f17701fb 20static
8bf17deb 21int lttng_kprobes_event_handler_pre(struct kprobe *p, struct pt_regs *regs)
d6d808f3 22{
a90917c3
MD
23 struct lttng_event *event =
24 container_of(p, struct lttng_event, u.kprobe.kp);
79150a49
JD
25 struct lttng_probe_ctx lttng_probe_ctx = {
26 .event = event,
ccecf3fb 27 .interruptible = !lttng_regs_irqs_disabled(regs),
79150a49 28 };
a90917c3 29 struct lttng_channel *chan = event->chan;
d6d808f3
MD
30 struct lib_ring_buffer_ctx ctx;
31 int ret;
32 unsigned long data = (unsigned long) p->addr;
33
585e5dcc 34 if (unlikely(!LTTNG_READ_ONCE(chan->session->active)))
f17701fb 35 return 0;
585e5dcc 36 if (unlikely(!LTTNG_READ_ONCE(chan->enabled)))
e64957da 37 return 0;
585e5dcc 38 if (unlikely(!LTTNG_READ_ONCE(event->enabled)))
e64957da
MD
39 return 0;
40
79150a49 41 lib_ring_buffer_ctx_init(&ctx, chan->chan, &lttng_probe_ctx, sizeof(data),
a90917c3 42 lttng_alignof(data), -1);
4e1f08f4 43 ret = chan->ops->event_reserve(&ctx, event->id);
d6d808f3 44 if (ret < 0)
f17701fb 45 return 0;
a90917c3 46 lib_ring_buffer_align_ctx(&ctx, lttng_alignof(data));
d6d808f3
MD
47 chan->ops->event_write(&ctx, &data, sizeof(data));
48 chan->ops->event_commit(&ctx);
f17701fb 49 return 0;
d6d808f3 50}
f17701fb 51
2b16f0c9
FD
52static
53int lttng_kprobes_event_notifier_handler_pre(struct kprobe *p, struct pt_regs *regs)
54{
55 struct lttng_event_notifier *event_notifier =
56 container_of(p, struct lttng_event_notifier, u.kprobe.kp);
c3eddb2e 57 struct lttng_kernel_notifier_ctx notif_ctx;
2b16f0c9
FD
58
59 if (unlikely(!READ_ONCE(event_notifier->enabled)))
60 return 0;
61
c3eddb2e
MD
62 notif_ctx.eval_capture = LTTNG_READ_ONCE(event_notifier->eval_capture);
63 event_notifier->send_notification(event_notifier, NULL, NULL, &notif_ctx);
2b16f0c9
FD
64
65 return 0;
66}
67
f17701fb
MD
68/*
69 * Create event description
70 */
71static
a90917c3 72int lttng_create_kprobe_event(const char *name, struct lttng_event *event)
f17701fb
MD
73{
74 struct lttng_event_field *field;
d3dbe23c 75 struct lttng_event_desc *desc;
f17701fb
MD
76 int ret;
77
d3dbe23c
MD
78 desc = kzalloc(sizeof(*event->desc), GFP_KERNEL);
79 if (!desc)
f17701fb 80 return -ENOMEM;
d3dbe23c
MD
81 desc->name = kstrdup(name, GFP_KERNEL);
82 if (!desc->name) {
f17701fb
MD
83 ret = -ENOMEM;
84 goto error_str;
85 }
d3dbe23c
MD
86 desc->nr_fields = 1;
87 desc->fields = field =
f17701fb 88 kzalloc(1 * sizeof(struct lttng_event_field), GFP_KERNEL);
0d1a681e
MD
89 if (!field) {
90 ret = -ENOMEM;
91 goto error_field;
92 }
f17701fb 93 field->name = "ip";
12bb2edb 94 field->type.type = lttng_kernel_type_integer;
ceabb767
MD
95 field->type.u.integer.size = sizeof(unsigned long) * CHAR_BIT;
96 field->type.u.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT;
97 field->type.u.integer.signedness = lttng_is_signed_type(unsigned long);
98 field->type.u.integer.reverse_byte_order = 0;
99 field->type.u.integer.base = 16;
28cbcb59 100 field->type.u.integer.encoding = lttng_kernel_string_encoding_none;
dc7f600a 101 desc->owner = THIS_MODULE;
d3dbe23c 102 event->desc = desc;
f17701fb
MD
103
104 return 0;
105
0d1a681e
MD
106error_field:
107 kfree(desc->name);
f17701fb 108error_str:
d3dbe23c 109 kfree(desc);
f17701fb
MD
110 return ret;
111}
112
2b16f0c9
FD
113/*
114 * Create event_notifier description
115 */
116static
117int lttng_create_kprobe_event_notifier(const char *name, struct lttng_event_notifier *event_notifier)
118{
119 struct lttng_event_desc *desc;
120 int ret;
121
122 desc = kzalloc(sizeof(*event_notifier->desc), GFP_KERNEL);
123 if (!desc)
124 return -ENOMEM;
125 desc->name = kstrdup(name, GFP_KERNEL);
126 if (!desc->name) {
127 ret = -ENOMEM;
128 goto error_str;
129 }
130 desc->nr_fields = 0;
131
132 desc->owner = THIS_MODULE;
133 event_notifier->desc = desc;
134
135 return 0;
136
137error_str:
138 kfree(desc);
139 return ret;
140}
141
8bf17deb
FD
142static
143int _lttng_kprobes_register(const char *symbol_name,
f17701fb
MD
144 uint64_t offset,
145 uint64_t addr,
8bf17deb
FD
146 struct lttng_kprobe *lttng_kp,
147 kprobe_pre_handler_t pre_handler)
f17701fb
MD
148{
149 int ret;
150
c37f2a9b
MD
151 /* Kprobes expects a NULL symbol name if unused */
152 if (symbol_name[0] == '\0')
153 symbol_name = NULL;
154
8bf17deb
FD
155 memset(&lttng_kp->kp, 0, sizeof(lttng_kp->kp));
156 lttng_kp->kp.pre_handler = pre_handler;
157
c37f2a9b 158 if (symbol_name) {
8bf17deb 159 lttng_kp->symbol_name =
f8695253 160 kzalloc(LTTNG_KERNEL_SYM_NAME_LEN * sizeof(char),
c37f2a9b 161 GFP_KERNEL);
8bf17deb 162 if (!lttng_kp->symbol_name) {
c37f2a9b
MD
163 ret = -ENOMEM;
164 goto name_error;
165 }
8bf17deb 166 memcpy(lttng_kp->symbol_name, symbol_name,
f8695253 167 LTTNG_KERNEL_SYM_NAME_LEN * sizeof(char));
8bf17deb 168 lttng_kp->kp.symbol_name = lttng_kp->symbol_name;
f17701fb 169 }
8bf17deb
FD
170
171 lttng_kp->kp.offset = offset;
172 lttng_kp->kp.addr = (void *) (unsigned long) addr;
16a9a591
MD
173
174 /*
196bfc6a 175 * Ensure the memory we just allocated don't notify page faults.
16a9a591
MD
176 * Well.. kprobes itself puts the page fault handler on the blacklist,
177 * but we can never be too careful.
178 */
263b6c88 179 wrapper_vmalloc_sync_mappings();
16a9a591 180
8bf17deb 181 ret = register_kprobe(&lttng_kp->kp);
f17701fb
MD
182 if (ret)
183 goto register_error;
8bf17deb 184
f17701fb
MD
185 return 0;
186
187register_error:
8bf17deb 188 kfree(lttng_kp->symbol_name);
f17701fb 189name_error:
8bf17deb
FD
190 return ret;
191}
192
193int lttng_kprobes_register_event(const char *name,
194 const char *symbol_name,
195 uint64_t offset,
196 uint64_t addr,
197 struct lttng_event *event)
198{
199 int ret;
200
201 ret = lttng_create_kprobe_event(name, event);
202 if (ret)
203 goto error;
204
205 ret = _lttng_kprobes_register(symbol_name, offset, addr,
206 &event->u.kprobe, lttng_kprobes_event_handler_pre);
207 if (ret)
208 goto register_error;
209
210 return 0;
211
212register_error:
0d1a681e 213 kfree(event->desc->fields);
f17701fb
MD
214 kfree(event->desc->name);
215 kfree(event->desc);
216error:
217 return ret;
218}
8bf17deb 219EXPORT_SYMBOL_GPL(lttng_kprobes_register_event);
f17701fb 220
2b16f0c9
FD
221int lttng_kprobes_register_event_notifier(const char *symbol_name,
222 uint64_t offset,
223 uint64_t addr,
224 struct lttng_event_notifier *event_notifier)
225{
226 int ret;
227 ret = lttng_create_kprobe_event_notifier(symbol_name, event_notifier);
228 if (ret)
229 goto error;
230
231 ret = _lttng_kprobes_register(symbol_name, offset, addr,
232 &event_notifier->u.kprobe, lttng_kprobes_event_notifier_handler_pre);
233 if (ret)
234 goto register_error;
235
236 return 0;
237
238register_error:
239 kfree(event_notifier->desc->name);
240 kfree(event_notifier->desc);
241error:
242 return ret;
243}
244EXPORT_SYMBOL_GPL(lttng_kprobes_register_event_notifier);
245
8bf17deb 246void lttng_kprobes_unregister_event(struct lttng_event *event)
f17701fb
MD
247{
248 unregister_kprobe(&event->u.kprobe.kp);
edeb3137 249}
8bf17deb 250EXPORT_SYMBOL_GPL(lttng_kprobes_unregister_event);
edeb3137 251
2b16f0c9
FD
252void lttng_kprobes_unregister_event_notifier(struct lttng_event_notifier *event_notifier)
253{
254 unregister_kprobe(&event_notifier->u.kprobe.kp);
255}
256EXPORT_SYMBOL_GPL(lttng_kprobes_unregister_event_notifier);
257
8bf17deb 258void lttng_kprobes_destroy_event_private(struct lttng_event *event)
edeb3137 259{
f17701fb 260 kfree(event->u.kprobe.symbol_name);
0d1a681e 261 kfree(event->desc->fields);
f17701fb
MD
262 kfree(event->desc->name);
263 kfree(event->desc);
264}
8bf17deb 265EXPORT_SYMBOL_GPL(lttng_kprobes_destroy_event_private);
d6d808f3 266
2b16f0c9
FD
267void lttng_kprobes_destroy_event_notifier_private(struct lttng_event_notifier *event_notifier)
268{
269 kfree(event_notifier->u.kprobe.symbol_name);
270 kfree(event_notifier->desc->name);
271 kfree(event_notifier->desc);
272}
273EXPORT_SYMBOL_GPL(lttng_kprobes_destroy_event_notifier_private);
274
d6d808f3 275MODULE_LICENSE("GPL and additional rights");
1c124020
MJ
276MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>");
277MODULE_DESCRIPTION("LTTng kprobes probes");
13ab8b0a
MD
278MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
279 __stringify(LTTNG_MODULES_MINOR_VERSION) "."
280 __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
281 LTTNG_MODULES_EXTRAVERSION);
This page took 0.061413 seconds and 4 git commands to generate.