event-rule: introduce event rule uprobe
[lttng-tools.git] / src / common / event-rule / uprobe.c
CommitLineData
df08d338
JR
1/*
2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8#include <assert.h>
9#include <common/error.h>
10#include <common/macros.h>
11#include <common/payload.h>
12#include <common/payload-view.h>
13#include <common/runas.h>
14#include <lttng/event-rule/event-rule-internal.h>
15#include <lttng/event-rule/uprobe-internal.h>
16#include <lttng/userspace-probe-internal.h>
17
18#define IS_UPROBE_EVENT_RULE(rule) \
19 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_UPROBE)
20
21static void lttng_event_rule_uprobe_destroy(struct lttng_event_rule *rule)
22{
23 struct lttng_event_rule_uprobe *uprobe;
24
25 uprobe = container_of(rule, struct lttng_event_rule_uprobe, parent);
26
27 lttng_userspace_probe_location_destroy(uprobe->location);
28 free(uprobe->name);
29 free(uprobe);
30}
31
32static bool lttng_event_rule_uprobe_validate(
33 const struct lttng_event_rule *rule)
34{
35 bool valid = false;
36 struct lttng_event_rule_uprobe *uprobe;
37
38 if (!rule) {
39 goto end;
40 }
41
42 uprobe = container_of(rule, struct lttng_event_rule_uprobe, parent);
43
44 /* Required field. */
45 if (!uprobe->name) {
46 ERR("Invalid uprobe event rule: a pattern must be set.");
47 goto end;
48 }
49
50 if (!uprobe->location) {
51 ERR("Invalid uprobe event rule: a location must be set.");
52 goto end;
53 }
54
55 valid = true;
56end:
57 return valid;
58}
59
60static int lttng_event_rule_uprobe_serialize(
61 const struct lttng_event_rule *rule,
62 struct lttng_payload *payload)
63{
64 int ret;
65 size_t name_len, header_offset, size_before_probe;
66 struct lttng_event_rule_uprobe *uprobe;
67 struct lttng_event_rule_uprobe_comm uprobe_comm = {};
68 struct lttng_event_rule_uprobe_comm *header;
69
70 if (!rule || !IS_UPROBE_EVENT_RULE(rule)) {
71 ret = -1;
72 goto end;
73 }
74
75 header_offset = payload->buffer.size;
76
77 DBG("Serializing uprobe event rule.");
78 uprobe = container_of(rule, struct lttng_event_rule_uprobe, parent);
79
80 name_len = strlen(uprobe->name) + 1;
81
82 uprobe_comm.name_len = name_len;
83
84 ret = lttng_dynamic_buffer_append(
85 &payload->buffer, &uprobe_comm, sizeof(uprobe_comm));
86 if (ret) {
87 goto end;
88 }
89 ret = lttng_dynamic_buffer_append(
90 &payload->buffer, uprobe->name, name_len);
91 if (ret) {
92 goto end;
93 }
94
95 size_before_probe = payload->buffer.size;
96
97 /* This serialize return the size taken in the buffer. */
98 ret = lttng_userspace_probe_location_serialize(
99 uprobe->location, payload);
100 if (ret < 0) {
101 goto end;
102 }
103
104 /* Update the header regarding the probe size. */
105 header = (struct lttng_event_rule_uprobe_comm
106 *) ((char *) payload->buffer.data +
107 header_offset);
108 header->location_len = payload->buffer.size - size_before_probe;
109
110 ret = 0;
111
112end:
113 return ret;
114}
115
116static bool lttng_event_rule_uprobe_is_equal(const struct lttng_event_rule *_a,
117 const struct lttng_event_rule *_b)
118{
119 bool is_equal = false;
120 struct lttng_event_rule_uprobe *a, *b;
121
122 a = container_of(_a, struct lttng_event_rule_uprobe, parent);
123 b = container_of(_b, struct lttng_event_rule_uprobe, parent);
124
125 /* uprobe is invalid if this is not true. */
126 assert(a->name);
127 assert(b->name);
128 if (strcmp(a->name, b->name)) {
129 goto end;
130 }
131
132 assert(a->location);
133 assert(b->location);
134 is_equal = lttng_userspace_probe_location_is_equal(
135 a->location, b->location);
136end:
137 return is_equal;
138}
139
140static enum lttng_error_code lttng_event_rule_uprobe_generate_filter_bytecode(
141 struct lttng_event_rule *rule, uid_t uid, gid_t gid)
142{
143 /* Nothing to do. */
144 return LTTNG_OK;
145}
146
147static const char *lttng_event_rule_uprobe_get_filter(
148 const struct lttng_event_rule *rule)
149{
150 /* Unsupported. */
151 return NULL;
152}
153
154static const struct lttng_filter_bytecode *
155lttng_event_rule_uprobe_get_filter_bytecode(const struct lttng_event_rule *rule)
156{
157 /* Unsupported. */
158 return NULL;
159}
160
161static struct lttng_event_exclusion *
162lttng_event_rule_uprobe_generate_exclusions(const struct lttng_event_rule *rule)
163{
164 /* Unsupported. */
165 return NULL;
166}
167
168struct lttng_event_rule *lttng_event_rule_uprobe_create()
169{
170 struct lttng_event_rule *rule = NULL;
171 struct lttng_event_rule_uprobe *urule;
172
173 urule = zmalloc(sizeof(struct lttng_event_rule_uprobe));
174 if (!urule) {
175 goto end;
176 }
177
178 rule = &urule->parent;
179 lttng_event_rule_init(&urule->parent, LTTNG_EVENT_RULE_TYPE_UPROBE);
180 urule->parent.validate = lttng_event_rule_uprobe_validate;
181 urule->parent.serialize = lttng_event_rule_uprobe_serialize;
182 urule->parent.equal = lttng_event_rule_uprobe_is_equal;
183 urule->parent.destroy = lttng_event_rule_uprobe_destroy;
184 urule->parent.generate_filter_bytecode =
185 lttng_event_rule_uprobe_generate_filter_bytecode;
186 urule->parent.get_filter = lttng_event_rule_uprobe_get_filter;
187 urule->parent.get_filter_bytecode =
188 lttng_event_rule_uprobe_get_filter_bytecode;
189 urule->parent.generate_exclusions =
190 lttng_event_rule_uprobe_generate_exclusions;
191end:
192 return rule;
193}
194
195LTTNG_HIDDEN
196ssize_t lttng_event_rule_uprobe_create_from_payload(
197 struct lttng_payload_view *view,
198 struct lttng_event_rule **_event_rule)
199{
200 ssize_t ret, offset = 0;
201 const struct lttng_event_rule_uprobe_comm *uprobe_comm;
202 const char *name;
203 struct lttng_buffer_view current_buffer_view;
204 struct lttng_event_rule *rule = NULL;
205 struct lttng_userspace_probe_location *location;
206 struct lttng_event_rule_uprobe *uprobe;
207 enum lttng_event_rule_status status;
208
209 if (!_event_rule) {
210 ret = -1;
211 goto end;
212 }
213
214 if (view->buffer.size < sizeof(*uprobe_comm)) {
215 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain header.");
216 ret = -1;
217 goto end;
218 }
219
220 current_buffer_view = lttng_buffer_view_from_view(
221 &view->buffer, offset, sizeof(*uprobe_comm));
222 uprobe_comm = (typeof(uprobe_comm)) current_buffer_view.data;
223
224 if (!uprobe_comm) {
225 ret = -1;
226 goto end;
227 }
228
229 rule = lttng_event_rule_uprobe_create();
230 if (!rule) {
231 ERR("Failed to create event rule uprobe.");
232 ret = -1;
233 goto end;
234 }
235
236 /* Skip to payload. */
237 offset += current_buffer_view.size;
238
239 /* Map the name. */
240 current_buffer_view = lttng_buffer_view_from_view(
241 &view->buffer, offset, uprobe_comm->name_len);
242 name = current_buffer_view.data;
243 if (!name) {
244 ret = -1;
245 goto end;
246 }
247
248 if (!lttng_buffer_view_contains_string(&current_buffer_view, name,
249 uprobe_comm->name_len)) {
250 ret = -1;
251 goto end;
252 }
253
254 /* Skip after the name. */
255 offset += uprobe_comm->name_len;
256
257 /* Map the location. */
258 struct lttng_payload_view current_payload_view =
259 lttng_payload_view_from_view(view, offset,
260 uprobe_comm->location_len);
261 ret = lttng_userspace_probe_location_create_from_payload(
262 &current_payload_view, &location);
263 if (ret < 0) {
264 ret = -1;
265 goto end;
266 }
267
268 assert(ret == uprobe_comm->location_len);
269
270 /* Skip after the location. */
271 offset += uprobe_comm->location_len;
272
273 uprobe = container_of(rule, struct lttng_event_rule_uprobe, parent);
274 uprobe->location = location;
275
276 status = lttng_event_rule_uprobe_set_name(rule, name);
277 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
278 ret = -1;
279 goto end;
280 }
281
282 if (!lttng_event_rule_uprobe_validate(rule)) {
283 ret = -1;
284 goto end;
285 }
286
287 *_event_rule = rule;
288 rule = NULL;
289 ret = offset;
290end:
291 lttng_event_rule_destroy(rule);
292 return ret;
293}
294
295enum lttng_event_rule_status lttng_event_rule_uprobe_set_location(
296 struct lttng_event_rule *rule,
297 const struct lttng_userspace_probe_location *location)
298{
299 struct lttng_userspace_probe_location *location_copy = NULL;
300 struct lttng_event_rule_uprobe *uprobe;
301 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
302
303 if (!rule || !IS_UPROBE_EVENT_RULE(rule) || !location) {
304 status = LTTNG_EVENT_RULE_STATUS_INVALID;
305 goto end;
306 }
307
308 uprobe = container_of(rule, struct lttng_event_rule_uprobe, parent);
309 location_copy = lttng_userspace_probe_location_copy(location);
310 if (!location_copy) {
311 status = LTTNG_EVENT_RULE_STATUS_ERROR;
312 goto end;
313 }
314
315 if (uprobe->location) {
316 lttng_userspace_probe_location_destroy(uprobe->location);
317 }
318
319 uprobe->location = location_copy;
320 location_copy = NULL;
321end:
322 lttng_userspace_probe_location_destroy(location_copy);
323 return status;
324}
325
326enum lttng_event_rule_status lttng_event_rule_uprobe_get_location(
327 const struct lttng_event_rule *rule,
328 const struct lttng_userspace_probe_location **location)
329{
330 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
331
332 if (!rule || !IS_UPROBE_EVENT_RULE(rule) || !location) {
333 status = LTTNG_EVENT_RULE_STATUS_INVALID;
334 goto end;
335 }
336
337 *location = lttng_event_rule_uprobe_get_location_mutable(rule);
338 if (!*location) {
339 status = LTTNG_EVENT_RULE_STATUS_UNSET;
340 goto end;
341 }
342
343end:
344 return status;
345}
346
347LTTNG_HIDDEN
348struct lttng_userspace_probe_location *
349lttng_event_rule_uprobe_get_location_mutable(
350 const struct lttng_event_rule *rule)
351{
352 struct lttng_event_rule_uprobe *uprobe;
353
354 assert(rule);
355 uprobe = container_of(rule, struct lttng_event_rule_uprobe, parent);
356
357 return uprobe->location;
358}
359
360enum lttng_event_rule_status lttng_event_rule_uprobe_set_name(
361 struct lttng_event_rule *rule, const char *name)
362{
363 char *name_copy = NULL;
364 struct lttng_event_rule_uprobe *uprobe;
365 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
366
367 if (!rule || !IS_UPROBE_EVENT_RULE(rule) || !name ||
368 strlen(name) == 0) {
369 status = LTTNG_EVENT_RULE_STATUS_INVALID;
370 goto end;
371 }
372
373 uprobe = container_of(rule, struct lttng_event_rule_uprobe, parent);
374 name_copy = strdup(name);
375 if (!name_copy) {
376 status = LTTNG_EVENT_RULE_STATUS_ERROR;
377 goto end;
378 }
379
380 if (uprobe->name) {
381 free(uprobe->name);
382 }
383
384 uprobe->name = name_copy;
385 name_copy = NULL;
386end:
387 return status;
388}
389
390enum lttng_event_rule_status lttng_event_rule_uprobe_get_name(
391 const struct lttng_event_rule *rule, const char **name)
392{
393 struct lttng_event_rule_uprobe *uprobe;
394 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
395
396 if (!rule || !IS_UPROBE_EVENT_RULE(rule) || !name) {
397 status = LTTNG_EVENT_RULE_STATUS_INVALID;
398 goto end;
399 }
400
401 uprobe = container_of(rule, struct lttng_event_rule_uprobe, parent);
402 if (!uprobe->name) {
403 status = LTTNG_EVENT_RULE_STATUS_UNSET;
404 goto end;
405 }
406
407 *name = uprobe->name;
408end:
409 return status;
410}
This page took 0.037413 seconds and 5 git commands to generate.