2 * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include "lttng/lttng-error.h"
10 #include <common/error.h>
11 #include <common/macros.h>
12 #include <common/payload.h>
13 #include <common/payload-view.h>
15 #include <lttng/constant.h>
16 #include <lttng/kernel-probe.h>
17 #include <lttng/kernel-probe-internal.h>
19 #include <sys/types.h>
20 #include <sys/unistd.h>
23 int lttng_kernel_probe_location_address_serialize(
24 const struct lttng_kernel_probe_location
*location
,
25 struct lttng_payload
*payload
);
28 int lttng_kernel_probe_location_symbol_serialize(
29 const struct lttng_kernel_probe_location
*location
,
30 struct lttng_payload
*payload
);
33 bool lttng_kernel_probe_location_address_is_equal(
34 const struct lttng_kernel_probe_location
*a
,
35 const struct lttng_kernel_probe_location
*b
);
38 bool lttng_kernel_probe_location_symbol_is_equal(
39 const struct lttng_kernel_probe_location
*a
,
40 const struct lttng_kernel_probe_location
*b
);
42 enum lttng_kernel_probe_location_type
lttng_kernel_probe_location_get_type(
43 const struct lttng_kernel_probe_location
*location
)
45 return location
? location
->type
:
46 LTTNG_KERNEL_PROBE_LOCATION_TYPE_UNKNOWN
;
50 void lttng_kernel_probe_location_address_destroy(
51 struct lttng_kernel_probe_location
*location
)
58 void lttng_kernel_probe_location_symbol_destroy(
59 struct lttng_kernel_probe_location
*location
)
61 struct lttng_kernel_probe_location_symbol
*location_symbol
= NULL
;
65 location_symbol
= container_of(location
,
66 struct lttng_kernel_probe_location_symbol
,
69 assert(location_symbol
);
71 free(location_symbol
->symbol_name
);
75 void lttng_kernel_probe_location_destroy(
76 struct lttng_kernel_probe_location
*location
)
82 switch (location
->type
) {
83 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
84 lttng_kernel_probe_location_address_destroy(location
);
86 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
87 lttng_kernel_probe_location_symbol_destroy(location
);
94 struct lttng_kernel_probe_location
*
95 lttng_kernel_probe_location_address_create(uint64_t address
)
97 struct lttng_kernel_probe_location
*ret
= NULL
;
98 struct lttng_kernel_probe_location_address
*location
;
100 location
= zmalloc(sizeof(*location
));
102 PERROR("Error allocating userspace probe location");
106 location
->address
= address
;
108 ret
= &location
->parent
;
109 ret
->type
= LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
;
110 ret
->equal
= lttng_kernel_probe_location_address_is_equal
;
111 ret
->serialize
= lttng_kernel_probe_location_address_serialize
;
117 struct lttng_kernel_probe_location
*
118 lttng_kernel_probe_location_symbol_create(const char *symbol_name
,
121 char *symbol_name_copy
= NULL
;
122 struct lttng_kernel_probe_location
*ret
= NULL
;
123 struct lttng_kernel_probe_location_symbol
*location
;
125 if (!symbol_name
|| strlen(symbol_name
) >= LTTNG_SYMBOL_NAME_LEN
) {
129 symbol_name_copy
= strdup(symbol_name
);
130 if (!symbol_name_copy
) {
131 PERROR("Failed to copy symbol name '%s'", symbol_name
);
135 location
= zmalloc(sizeof(*location
));
137 PERROR("Failed to allocate kernel symbol probe location");
141 location
->symbol_name
= symbol_name_copy
;
142 location
->offset
= offset
;
144 ret
= &location
->parent
;
145 ret
->type
= LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
;
146 ret
->equal
= lttng_kernel_probe_location_symbol_is_equal
;
147 ret
->serialize
= lttng_kernel_probe_location_symbol_serialize
;
151 free(symbol_name_copy
);
156 enum lttng_kernel_probe_location_status
157 lttng_kernel_probe_location_address_get_address(
158 const struct lttng_kernel_probe_location
*location
,
161 enum lttng_kernel_probe_location_status ret
=
162 LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
;
163 struct lttng_kernel_probe_location_address
*address_location
;
167 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
168 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
) {
169 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
170 ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID
;
174 address_location
= container_of(location
,
175 struct lttng_kernel_probe_location_address
, parent
);
176 *offset
= address_location
->address
;
181 const char *lttng_kernel_probe_location_symbol_get_name(
182 const struct lttng_kernel_probe_location
*location
)
184 const char *ret
= NULL
;
185 struct lttng_kernel_probe_location_symbol
*symbol_location
;
187 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
188 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
) {
189 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
193 symbol_location
= container_of(location
,
194 struct lttng_kernel_probe_location_symbol
, parent
);
195 ret
= symbol_location
->symbol_name
;
200 enum lttng_kernel_probe_location_status
201 lttng_kernel_probe_location_symbol_get_offset(
202 const struct lttng_kernel_probe_location
*location
,
205 enum lttng_kernel_probe_location_status ret
=
206 LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
;
207 struct lttng_kernel_probe_location_symbol
*symbol_location
;
211 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
212 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
) {
213 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
214 ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID
;
218 symbol_location
= container_of(location
,
219 struct lttng_kernel_probe_location_symbol
, parent
);
220 *offset
= symbol_location
->offset
;
226 int lttng_kernel_probe_location_symbol_serialize(
227 const struct lttng_kernel_probe_location
*location
,
228 struct lttng_payload
*payload
)
231 size_t symbol_name_len
;
232 size_t original_payload_size
;
233 struct lttng_kernel_probe_location_symbol
*location_symbol
;
234 struct lttng_kernel_probe_location_symbol_comm location_symbol_comm
;
236 if (!location
|| !payload
) {
237 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
238 ret
= -LTTNG_ERR_INVALID
;
242 assert(lttng_kernel_probe_location_get_type(location
) ==
243 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
245 original_payload_size
= payload
->buffer
.size
;
246 location_symbol
= container_of(location
,
247 struct lttng_kernel_probe_location_symbol
, parent
);
249 if (!location_symbol
->symbol_name
) {
250 ret
= -LTTNG_ERR_INVALID
;
254 symbol_name_len
= strlen(location_symbol
->symbol_name
);
255 if (symbol_name_len
== 0) {
256 ret
= -LTTNG_ERR_INVALID
;
260 location_symbol_comm
.symbol_len
= symbol_name_len
+ 1;
261 location_symbol_comm
.offset
= location_symbol
->offset
;
263 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
264 &location_symbol_comm
, sizeof(location_symbol_comm
));
266 ret
= -LTTNG_ERR_INVALID
;
270 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
271 location_symbol
->symbol_name
,
272 location_symbol_comm
.symbol_len
);
274 ret
= -LTTNG_ERR_INVALID
;
278 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
284 int lttng_kernel_probe_location_address_serialize(
285 const struct lttng_kernel_probe_location
*location
,
286 struct lttng_payload
*payload
)
289 size_t original_payload_size
;
290 struct lttng_kernel_probe_location_address
*location_address
;
291 struct lttng_kernel_probe_location_address_comm location_address_comm
;
294 assert(lttng_kernel_probe_location_get_type(location
) ==
295 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
297 original_payload_size
= payload
->buffer
.size
;
298 location_address
= container_of(location
,
299 struct lttng_kernel_probe_location_address
,
302 location_address_comm
.address
= location_address
->address
;
304 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
305 &location_address_comm
,
306 sizeof(location_address_comm
));
308 ret
= -LTTNG_ERR_INVALID
;
312 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
318 int lttng_kernel_probe_location_serialize(
319 const struct lttng_kernel_probe_location
*location
,
320 struct lttng_payload
*payload
)
323 size_t original_payload_size
;
324 struct lttng_kernel_probe_location_comm location_generic_comm
= {};
326 if (!location
|| !payload
) {
327 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
328 ret
= -LTTNG_ERR_INVALID
;
332 original_payload_size
= payload
->buffer
.size
;
333 location_generic_comm
.type
= (int8_t) location
->type
;
334 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
335 &location_generic_comm
,
336 sizeof(location_generic_comm
));
341 ret
= location
->serialize(location
, payload
);
346 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
352 int lttng_kernel_probe_location_symbol_create_from_payload(
353 struct lttng_payload_view
*view
,
354 struct lttng_kernel_probe_location
**location
)
356 struct lttng_kernel_probe_location_symbol_comm
*location_symbol_comm
;
357 const char *symbol_name_src
;
359 size_t expected_size
;
363 if (view
->buffer
.size
< sizeof(*location_symbol_comm
)) {
364 ret
= -LTTNG_ERR_INVALID
;
368 location_symbol_comm
=
369 (typeof(location_symbol_comm
)) view
->buffer
.data
;
371 expected_size
= sizeof(*location_symbol_comm
) +
372 location_symbol_comm
->symbol_len
;
374 if (view
->buffer
.size
< expected_size
) {
375 ret
= -LTTNG_ERR_INVALID
;
379 symbol_name_src
= view
->buffer
.data
+ sizeof(*location_symbol_comm
);
381 if (!lttng_buffer_view_contains_string(&view
->buffer
, symbol_name_src
,
382 location_symbol_comm
->symbol_len
)) {
383 ret
= -LTTNG_ERR_INVALID
;
387 *location
= lttng_kernel_probe_location_symbol_create(
388 symbol_name_src
, location_symbol_comm
->offset
);
390 ret
= -LTTNG_ERR_INVALID
;
394 ret
= (ssize_t
) expected_size
;
400 ssize_t
lttng_kernel_probe_location_address_create_from_payload(
401 struct lttng_payload_view
*view
,
402 struct lttng_kernel_probe_location
**location
)
404 struct lttng_kernel_probe_location_address_comm
*location_address_comm
;
406 size_t expected_size
;
410 expected_size
= sizeof(*location_address_comm
);
412 if (view
->buffer
.size
< expected_size
) {
413 ret
= -LTTNG_ERR_INVALID
;
417 location_address_comm
=
418 (typeof(location_address_comm
)) view
->buffer
.data
;
420 *location
= lttng_kernel_probe_location_address_create(location_address_comm
->address
);
422 ret
= -LTTNG_ERR_INVALID
;
426 ret
= (size_t) expected_size
;
432 ssize_t
lttng_kernel_probe_location_create_from_payload(
433 struct lttng_payload_view
*view
,
434 struct lttng_kernel_probe_location
**location
)
436 struct lttng_kernel_probe_location_comm
*probe_location_comm
;
437 enum lttng_kernel_probe_location_type type
;
438 ssize_t consumed
= 0;
444 if (view
->buffer
.size
<= sizeof(*probe_location_comm
)) {
445 ret
= -LTTNG_ERR_INVALID
;
449 probe_location_comm
= (typeof(probe_location_comm
)) view
->buffer
.data
;
450 type
= (enum lttng_kernel_probe_location_type
) probe_location_comm
->type
;
451 consumed
+= sizeof(*probe_location_comm
);
454 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
456 struct lttng_payload_view location_view
=
457 lttng_payload_view_from_view(
460 ret
= lttng_kernel_probe_location_symbol_create_from_payload(
461 &location_view
, location
);
464 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
466 struct lttng_payload_view location_view
=
467 lttng_payload_view_from_view(view
, consumed
, -1);
469 ret
= lttng_kernel_probe_location_address_create_from_payload(
470 &location_view
, location
);
474 ret
= -LTTNG_ERR_INVALID
;
479 ret
= -LTTNG_ERR_INVALID
;
490 bool lttng_kernel_probe_location_address_is_equal(
491 const struct lttng_kernel_probe_location
*_a
,
492 const struct lttng_kernel_probe_location
*_b
)
494 bool is_equal
= false;
495 struct lttng_kernel_probe_location_address
*a
, *b
;
497 a
= container_of(_a
, struct lttng_kernel_probe_location_address
,
499 b
= container_of(_b
, struct lttng_kernel_probe_location_address
,
502 if (a
->address
!= b
->address
) {
513 bool lttng_kernel_probe_location_symbol_is_equal(
514 const struct lttng_kernel_probe_location
*_a
,
515 const struct lttng_kernel_probe_location
*_b
)
517 bool is_equal
= false;
518 struct lttng_kernel_probe_location_symbol
*a
, *b
;
520 a
= container_of(_a
, struct lttng_kernel_probe_location_symbol
,
522 b
= container_of(_b
, struct lttng_kernel_probe_location_symbol
,
525 assert(a
->symbol_name
);
526 assert(b
->symbol_name
);
527 if (strcmp(a
->symbol_name
, b
->symbol_name
)) {
531 if (a
->offset
!= b
->offset
) {
542 bool lttng_kernel_probe_location_is_equal(
543 const struct lttng_kernel_probe_location
*a
,
544 const struct lttng_kernel_probe_location
*b
)
546 bool is_equal
= false;
557 if (a
->type
!= b
->type
) {
561 is_equal
= a
->equal
? a
->equal(a
, b
) : true;