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