3f9b02356740055f146fcadf6b77004c62e5a096
[lttng-modules.git] / src / probes / lttng-kprobes.c
1 /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
2 *
3 * probes/lttng-kprobes.c
4 *
5 * LTTng kprobes integration module.
6 *
7 * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 */
9
10 #include <linux/module.h>
11 #include <linux/kprobes.h>
12 #include <linux/slab.h>
13 #include <lttng/events.h>
14 #include <ringbuffer/frontend_types.h>
15 #include <wrapper/vmalloc.h>
16 #include <wrapper/irqflags.h>
17 #include <lttng/tracer.h>
18 #include <blacklist/kprobes.h>
19
20 static
21 int lttng_kprobes_event_handler_pre(struct kprobe *p, struct pt_regs *regs)
22 {
23 struct lttng_event *event =
24 container_of(p, struct lttng_event, u.kprobe.kp);
25 struct lttng_probe_ctx lttng_probe_ctx = {
26 .event = event,
27 .interruptible = !lttng_regs_irqs_disabled(regs),
28 };
29 struct lttng_channel *chan = event->chan;
30 struct lib_ring_buffer_ctx ctx;
31 int ret;
32 unsigned long data = (unsigned long) p->addr;
33
34 if (unlikely(!LTTNG_READ_ONCE(chan->session->active)))
35 return 0;
36 if (unlikely(!LTTNG_READ_ONCE(chan->enabled)))
37 return 0;
38 if (unlikely(!LTTNG_READ_ONCE(event->enabled)))
39 return 0;
40
41 lib_ring_buffer_ctx_init(&ctx, chan->chan, &lttng_probe_ctx, sizeof(data),
42 lttng_alignof(data), -1);
43 ret = chan->ops->event_reserve(&ctx, event->id);
44 if (ret < 0)
45 return 0;
46 lib_ring_buffer_align_ctx(&ctx, lttng_alignof(data));
47 chan->ops->event_write(&ctx, &data, sizeof(data));
48 chan->ops->event_commit(&ctx);
49 return 0;
50 }
51
52 /*
53 * Create event description
54 */
55 static
56 int lttng_create_kprobe_event(const char *name, struct lttng_event *event)
57 {
58 struct lttng_event_field *field;
59 struct lttng_event_desc *desc;
60 int ret;
61
62 desc = kzalloc(sizeof(*event->desc), GFP_KERNEL);
63 if (!desc)
64 return -ENOMEM;
65 desc->name = kstrdup(name, GFP_KERNEL);
66 if (!desc->name) {
67 ret = -ENOMEM;
68 goto error_str;
69 }
70 desc->nr_fields = 1;
71 desc->fields = field =
72 kzalloc(1 * sizeof(struct lttng_event_field), GFP_KERNEL);
73 if (!field) {
74 ret = -ENOMEM;
75 goto error_field;
76 }
77 field->name = "ip";
78 field->type.atype = atype_integer;
79 field->type.u.integer.size = sizeof(unsigned long) * CHAR_BIT;
80 field->type.u.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT;
81 field->type.u.integer.signedness = lttng_is_signed_type(unsigned long);
82 field->type.u.integer.reverse_byte_order = 0;
83 field->type.u.integer.base = 16;
84 field->type.u.integer.encoding = lttng_encode_none;
85 desc->owner = THIS_MODULE;
86 event->desc = desc;
87
88 return 0;
89
90 error_field:
91 kfree(desc->name);
92 error_str:
93 kfree(desc);
94 return ret;
95 }
96
97 static
98 int _lttng_kprobes_register(const char *symbol_name,
99 uint64_t offset,
100 uint64_t addr,
101 struct lttng_kprobe *lttng_kp,
102 kprobe_pre_handler_t pre_handler)
103 {
104 int ret;
105
106 /* Kprobes expects a NULL symbol name if unused */
107 if (symbol_name[0] == '\0')
108 symbol_name = NULL;
109
110 memset(&lttng_kp->kp, 0, sizeof(lttng_kp->kp));
111 lttng_kp->kp.pre_handler = pre_handler;
112
113 if (symbol_name) {
114 lttng_kp->symbol_name =
115 kzalloc(LTTNG_KERNEL_SYM_NAME_LEN * sizeof(char),
116 GFP_KERNEL);
117 if (!lttng_kp->symbol_name) {
118 ret = -ENOMEM;
119 goto name_error;
120 }
121 memcpy(lttng_kp->symbol_name, symbol_name,
122 LTTNG_KERNEL_SYM_NAME_LEN * sizeof(char));
123 lttng_kp->kp.symbol_name = lttng_kp->symbol_name;
124 }
125
126 lttng_kp->kp.offset = offset;
127 lttng_kp->kp.addr = (void *) (unsigned long) addr;
128
129 /*
130 * Ensure the memory we just allocated don't trigger page faults.
131 * Well.. kprobes itself puts the page fault handler on the blacklist,
132 * but we can never be too careful.
133 */
134 wrapper_vmalloc_sync_mappings();
135
136 ret = register_kprobe(&lttng_kp->kp);
137 if (ret)
138 goto register_error;
139
140 return 0;
141
142 register_error:
143 kfree(lttng_kp->symbol_name);
144 name_error:
145 return ret;
146 }
147
148 int lttng_kprobes_register_event(const char *name,
149 const char *symbol_name,
150 uint64_t offset,
151 uint64_t addr,
152 struct lttng_event *event)
153 {
154 int ret;
155
156 ret = lttng_create_kprobe_event(name, event);
157 if (ret)
158 goto error;
159
160 ret = _lttng_kprobes_register(symbol_name, offset, addr,
161 &event->u.kprobe, lttng_kprobes_event_handler_pre);
162 if (ret)
163 goto register_error;
164
165 return 0;
166
167 register_error:
168 kfree(event->desc->fields);
169 kfree(event->desc->name);
170 kfree(event->desc);
171 error:
172 return ret;
173 }
174 EXPORT_SYMBOL_GPL(lttng_kprobes_register_event);
175
176 void lttng_kprobes_unregister_event(struct lttng_event *event)
177 {
178 unregister_kprobe(&event->u.kprobe.kp);
179 }
180 EXPORT_SYMBOL_GPL(lttng_kprobes_unregister_event);
181
182 void lttng_kprobes_destroy_event_private(struct lttng_event *event)
183 {
184 kfree(event->u.kprobe.symbol_name);
185 kfree(event->desc->fields);
186 kfree(event->desc->name);
187 kfree(event->desc);
188 }
189 EXPORT_SYMBOL_GPL(lttng_kprobes_destroy_event_private);
190
191 MODULE_LICENSE("GPL and additional rights");
192 MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>");
193 MODULE_DESCRIPTION("LTTng kprobes probes");
194 MODULE_VERSION(__stringify(LTTNG_MODULES_MAJOR_VERSION) "."
195 __stringify(LTTNG_MODULES_MINOR_VERSION) "."
196 __stringify(LTTNG_MODULES_PATCHLEVEL_VERSION)
197 LTTNG_MODULES_EXTRAVERSION);
This page took 0.03222 seconds and 3 git commands to generate.