2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/credentials.h>
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>
19 #define IS_UPROBE_EVENT_RULE(rule) \
20 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_UPROBE)
22 static void lttng_event_rule_uprobe_destroy(struct lttng_event_rule
*rule
)
24 struct lttng_event_rule_uprobe
*uprobe
;
26 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
28 lttng_userspace_probe_location_destroy(uprobe
->location
);
33 static bool lttng_event_rule_uprobe_validate(
34 const struct lttng_event_rule
*rule
)
37 struct lttng_event_rule_uprobe
*uprobe
;
43 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
47 ERR("Invalid uprobe event rule: a pattern must be set.");
51 if (!uprobe
->location
) {
52 ERR("Invalid uprobe event rule: a location must be set.");
61 static int lttng_event_rule_uprobe_serialize(
62 const struct lttng_event_rule
*rule
,
63 struct lttng_payload
*payload
)
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
;
71 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
)) {
76 header_offset
= payload
->buffer
.size
;
78 DBG("Serializing uprobe event rule.");
79 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
81 name_len
= strlen(uprobe
->name
) + 1;
83 uprobe_comm
.name_len
= name_len
;
85 ret
= lttng_dynamic_buffer_append(
86 &payload
->buffer
, &uprobe_comm
, sizeof(uprobe_comm
));
90 ret
= lttng_dynamic_buffer_append(
91 &payload
->buffer
, uprobe
->name
, name_len
);
96 size_before_probe
= payload
->buffer
.size
;
98 /* This serialize return the size taken in the buffer. */
99 ret
= lttng_userspace_probe_location_serialize(
100 uprobe
->location
, payload
);
105 /* Update the header regarding the probe size. */
106 header
= (struct lttng_event_rule_uprobe_comm
107 *) ((char *) payload
->buffer
.data
+
109 header
->location_len
= payload
->buffer
.size
- size_before_probe
;
117 static bool lttng_event_rule_uprobe_is_equal(const struct lttng_event_rule
*_a
,
118 const struct lttng_event_rule
*_b
)
120 bool is_equal
= false;
121 struct lttng_event_rule_uprobe
*a
, *b
;
123 a
= container_of(_a
, struct lttng_event_rule_uprobe
, parent
);
124 b
= container_of(_b
, struct lttng_event_rule_uprobe
, parent
);
126 /* uprobe is invalid if this is not true. */
129 if (strcmp(a
->name
, b
->name
)) {
135 is_equal
= lttng_userspace_probe_location_is_equal(
136 a
->location
, b
->location
);
141 static enum lttng_error_code
lttng_event_rule_uprobe_generate_filter_bytecode(
142 struct lttng_event_rule
*rule
,
143 const struct lttng_credentials
*creds
)
149 static const char *lttng_event_rule_uprobe_get_filter(
150 const struct lttng_event_rule
*rule
)
156 static const struct lttng_filter_bytecode
*
157 lttng_event_rule_uprobe_get_filter_bytecode(const struct lttng_event_rule
*rule
)
163 static struct lttng_event_exclusion
*
164 lttng_event_rule_uprobe_generate_exclusions(const struct lttng_event_rule
*rule
)
170 struct lttng_event_rule
*lttng_event_rule_uprobe_create()
172 struct lttng_event_rule
*rule
= NULL
;
173 struct lttng_event_rule_uprobe
*urule
;
175 urule
= zmalloc(sizeof(struct lttng_event_rule_uprobe
));
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
;
198 ssize_t
lttng_event_rule_uprobe_create_from_payload(
199 struct lttng_payload_view
*view
,
200 struct lttng_event_rule
**_event_rule
)
202 ssize_t ret
, offset
= 0;
203 const struct lttng_event_rule_uprobe_comm
*uprobe_comm
;
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
;
216 current_buffer_view
= lttng_buffer_view_from_view(
217 &view
->buffer
, offset
, sizeof(*uprobe_comm
));
218 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
219 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain header");
224 uprobe_comm
= (typeof(uprobe_comm
)) current_buffer_view
.data
;
226 rule
= lttng_event_rule_uprobe_create();
228 ERR("Failed to create event rule uprobe");
233 /* Skip to payload. */
234 offset
+= current_buffer_view
.size
;
237 current_buffer_view
= lttng_buffer_view_from_view(
238 &view
->buffer
, offset
, uprobe_comm
->name_len
);
239 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
244 name
= current_buffer_view
.data
;
245 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, name
,
246 uprobe_comm
->name_len
)) {
251 /* Skip after the name. */
252 offset
+= uprobe_comm
->name_len
;
254 /* Map the location. */
256 struct lttng_payload_view current_payload_view
=
257 lttng_payload_view_from_view(view
, offset
,
258 uprobe_comm
->location_len
);
260 if (!lttng_payload_view_is_valid(¤t_payload_view
)) {
261 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain location");
266 ret
= lttng_userspace_probe_location_create_from_payload(
267 ¤t_payload_view
, &location
);
274 assert(ret
== uprobe_comm
->location_len
);
276 /* Skip after the location. */
277 offset
+= uprobe_comm
->location_len
;
279 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
280 uprobe
->location
= location
;
282 status
= lttng_event_rule_uprobe_set_name(rule
, name
);
283 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
288 if (!lttng_event_rule_uprobe_validate(rule
)) {
297 lttng_event_rule_destroy(rule
);
301 enum lttng_event_rule_status
lttng_event_rule_uprobe_set_location(
302 struct lttng_event_rule
*rule
,
303 const struct lttng_userspace_probe_location
*location
)
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
;
309 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
310 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
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
;
321 if (uprobe
->location
) {
322 lttng_userspace_probe_location_destroy(uprobe
->location
);
325 uprobe
->location
= location_copy
;
326 location_copy
= NULL
;
328 lttng_userspace_probe_location_destroy(location_copy
);
332 enum 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
)
336 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
338 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
339 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
343 *location
= lttng_event_rule_uprobe_get_location_mutable(rule
);
345 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
354 struct lttng_userspace_probe_location
*
355 lttng_event_rule_uprobe_get_location_mutable(
356 const struct lttng_event_rule
*rule
)
358 struct lttng_event_rule_uprobe
*uprobe
;
361 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
363 return uprobe
->location
;
366 enum lttng_event_rule_status
lttng_event_rule_uprobe_set_name(
367 struct lttng_event_rule
*rule
, const char *name
)
369 char *name_copy
= NULL
;
370 struct lttng_event_rule_uprobe
*uprobe
;
371 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
373 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
||
375 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
379 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
380 name_copy
= strdup(name
);
382 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
390 uprobe
->name
= name_copy
;
396 enum lttng_event_rule_status
lttng_event_rule_uprobe_get_name(
397 const struct lttng_event_rule
*rule
, const char **name
)
399 struct lttng_event_rule_uprobe
*uprobe
;
400 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
402 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
) {
403 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
407 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
409 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
413 *name
= uprobe
->name
;