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"
9 #include <common/error.hpp>
10 #include <common/hashtable/hashtable.hpp>
11 #include <common/hashtable/utils.hpp>
12 #include <common/macros.hpp>
13 #include <common/mi-lttng.hpp>
14 #include <common/payload-view.hpp>
15 #include <common/payload.hpp>
17 #include <lttng/constant.h>
18 #include <lttng/kernel-probe-internal.hpp>
19 #include <lttng/kernel-probe.h>
21 #include <sys/types.h>
25 int lttng_kernel_probe_location_address_serialize(
26 const struct lttng_kernel_probe_location
*location
,
27 struct lttng_payload
*payload
);
30 int lttng_kernel_probe_location_symbol_serialize(
31 const struct lttng_kernel_probe_location
*location
,
32 struct lttng_payload
*payload
);
35 bool lttng_kernel_probe_location_address_is_equal(
36 const struct lttng_kernel_probe_location
*a
,
37 const struct lttng_kernel_probe_location
*b
);
40 bool lttng_kernel_probe_location_symbol_is_equal(
41 const struct lttng_kernel_probe_location
*a
,
42 const struct lttng_kernel_probe_location
*b
);
45 unsigned long lttng_kernel_probe_location_address_hash(
46 const struct lttng_kernel_probe_location
*location
);
49 unsigned long lttng_kernel_probe_location_symbol_hash(
50 const struct lttng_kernel_probe_location
*location
);
53 enum lttng_error_code
lttng_kernel_probe_location_address_mi_serialize(
54 const struct lttng_kernel_probe_location
*location
,
55 struct mi_writer
*writer
);
58 enum lttng_error_code
lttng_kernel_probe_location_symbol_mi_serialize(
59 const struct lttng_kernel_probe_location
*location
,
60 struct mi_writer
*writer
);
62 enum lttng_kernel_probe_location_type
lttng_kernel_probe_location_get_type(
63 const struct lttng_kernel_probe_location
*location
)
65 return location
? location
->type
:
66 LTTNG_KERNEL_PROBE_LOCATION_TYPE_UNKNOWN
;
70 void lttng_kernel_probe_location_address_destroy(
71 struct lttng_kernel_probe_location
*location
)
73 LTTNG_ASSERT(location
);
78 void lttng_kernel_probe_location_symbol_destroy(
79 struct lttng_kernel_probe_location
*location
)
81 struct lttng_kernel_probe_location_symbol
*location_symbol
= NULL
;
83 LTTNG_ASSERT(location
);
85 location_symbol
= container_of(location
,
86 struct lttng_kernel_probe_location_symbol
,
89 LTTNG_ASSERT(location_symbol
);
91 free(location_symbol
->symbol_name
);
95 void lttng_kernel_probe_location_destroy(
96 struct lttng_kernel_probe_location
*location
)
102 switch (location
->type
) {
103 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
104 lttng_kernel_probe_location_address_destroy(location
);
106 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
107 lttng_kernel_probe_location_symbol_destroy(location
);
114 struct lttng_kernel_probe_location
*
115 lttng_kernel_probe_location_address_create(uint64_t address
)
117 struct lttng_kernel_probe_location
*ret
= NULL
;
118 struct lttng_kernel_probe_location_address
*location
;
120 location
= zmalloc
<lttng_kernel_probe_location_address
>();
122 PERROR("Error allocating userspace probe location.");
126 location
->address
= address
;
128 ret
= &location
->parent
;
129 ret
->type
= LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
;
130 ret
->equal
= lttng_kernel_probe_location_address_is_equal
;
131 ret
->serialize
= lttng_kernel_probe_location_address_serialize
;
132 ret
->hash
= lttng_kernel_probe_location_address_hash
;
133 ret
->mi_serialize
= lttng_kernel_probe_location_address_mi_serialize
;
139 struct lttng_kernel_probe_location
*
140 lttng_kernel_probe_location_symbol_create(const char *symbol_name
,
143 char *symbol_name_copy
= NULL
;
144 struct lttng_kernel_probe_location
*ret
= NULL
;
145 struct lttng_kernel_probe_location_symbol
*location
;
147 if (!symbol_name
|| strlen(symbol_name
) >= LTTNG_SYMBOL_NAME_LEN
) {
151 symbol_name_copy
= strdup(symbol_name
);
152 if (!symbol_name_copy
) {
153 PERROR("Failed to copy symbol name '%s'", symbol_name
);
157 location
= zmalloc
<lttng_kernel_probe_location_symbol
>();
159 PERROR("Failed to allocate kernel symbol probe location");
163 location
->symbol_name
= symbol_name_copy
;
164 location
->offset
= offset
;
166 ret
= &location
->parent
;
167 ret
->type
= LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
;
168 ret
->equal
= lttng_kernel_probe_location_symbol_is_equal
;
169 ret
->serialize
= lttng_kernel_probe_location_symbol_serialize
;
170 ret
->hash
= lttng_kernel_probe_location_symbol_hash
;
171 ret
->mi_serialize
= lttng_kernel_probe_location_symbol_mi_serialize
;
175 free(symbol_name_copy
);
180 enum lttng_kernel_probe_location_status
181 lttng_kernel_probe_location_address_get_address(
182 const struct lttng_kernel_probe_location
*location
,
185 enum lttng_kernel_probe_location_status ret
=
186 LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
;
187 struct lttng_kernel_probe_location_address
*address_location
;
189 LTTNG_ASSERT(offset
);
191 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
192 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
) {
193 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
194 ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID
;
198 address_location
= container_of(location
,
199 struct lttng_kernel_probe_location_address
, parent
);
200 *offset
= address_location
->address
;
205 const char *lttng_kernel_probe_location_symbol_get_name(
206 const struct lttng_kernel_probe_location
*location
)
208 const char *ret
= NULL
;
209 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__
);
217 symbol_location
= container_of(location
,
218 struct lttng_kernel_probe_location_symbol
, parent
);
219 ret
= symbol_location
->symbol_name
;
224 enum lttng_kernel_probe_location_status
225 lttng_kernel_probe_location_symbol_get_offset(
226 const struct lttng_kernel_probe_location
*location
,
229 enum lttng_kernel_probe_location_status ret
=
230 LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
;
231 struct lttng_kernel_probe_location_symbol
*symbol_location
;
233 LTTNG_ASSERT(offset
);
235 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
236 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
) {
237 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
238 ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID
;
242 symbol_location
= container_of(location
,
243 struct lttng_kernel_probe_location_symbol
, parent
);
244 *offset
= symbol_location
->offset
;
250 int lttng_kernel_probe_location_symbol_serialize(
251 const struct lttng_kernel_probe_location
*location
,
252 struct lttng_payload
*payload
)
255 size_t symbol_name_len
;
256 size_t original_payload_size
;
257 struct lttng_kernel_probe_location_symbol
*location_symbol
;
258 struct lttng_kernel_probe_location_symbol_comm location_symbol_comm
;
260 if (!location
|| !payload
) {
261 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
262 ret
= -LTTNG_ERR_INVALID
;
266 LTTNG_ASSERT(lttng_kernel_probe_location_get_type(location
) ==
267 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
269 original_payload_size
= payload
->buffer
.size
;
270 location_symbol
= container_of(location
,
271 struct lttng_kernel_probe_location_symbol
, parent
);
273 if (!location_symbol
->symbol_name
) {
274 ret
= -LTTNG_ERR_INVALID
;
278 symbol_name_len
= strlen(location_symbol
->symbol_name
);
279 if (symbol_name_len
== 0) {
280 ret
= -LTTNG_ERR_INVALID
;
284 location_symbol_comm
.symbol_len
= symbol_name_len
+ 1;
285 location_symbol_comm
.offset
= location_symbol
->offset
;
287 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
288 &location_symbol_comm
, sizeof(location_symbol_comm
));
290 ret
= -LTTNG_ERR_INVALID
;
294 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
295 location_symbol
->symbol_name
,
296 location_symbol_comm
.symbol_len
);
298 ret
= -LTTNG_ERR_INVALID
;
302 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
308 int lttng_kernel_probe_location_address_serialize(
309 const struct lttng_kernel_probe_location
*location
,
310 struct lttng_payload
*payload
)
313 size_t original_payload_size
;
314 struct lttng_kernel_probe_location_address
*location_address
;
315 struct lttng_kernel_probe_location_address_comm location_address_comm
;
317 LTTNG_ASSERT(location
);
318 LTTNG_ASSERT(lttng_kernel_probe_location_get_type(location
) ==
319 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
321 original_payload_size
= payload
->buffer
.size
;
322 location_address
= container_of(location
,
323 struct lttng_kernel_probe_location_address
,
326 location_address_comm
.address
= location_address
->address
;
328 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
329 &location_address_comm
,
330 sizeof(location_address_comm
));
332 ret
= -LTTNG_ERR_INVALID
;
336 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
341 int lttng_kernel_probe_location_serialize(
342 const struct lttng_kernel_probe_location
*location
,
343 struct lttng_payload
*payload
)
346 size_t original_payload_size
;
347 struct lttng_kernel_probe_location_comm location_generic_comm
= {};
349 if (!location
|| !payload
) {
350 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
351 ret
= -LTTNG_ERR_INVALID
;
355 original_payload_size
= payload
->buffer
.size
;
356 location_generic_comm
.type
= (int8_t) location
->type
;
357 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
358 &location_generic_comm
,
359 sizeof(location_generic_comm
));
364 ret
= location
->serialize(location
, payload
);
369 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
375 int lttng_kernel_probe_location_symbol_create_from_payload(
376 struct lttng_payload_view
*view
,
377 struct lttng_kernel_probe_location
**location
)
379 struct lttng_kernel_probe_location_symbol_comm
*location_symbol_comm
;
380 const char *symbol_name_src
;
382 size_t expected_size
;
384 LTTNG_ASSERT(location
);
386 if (view
->buffer
.size
< sizeof(*location_symbol_comm
)) {
387 ret
= -LTTNG_ERR_INVALID
;
391 location_symbol_comm
=
392 (typeof(location_symbol_comm
)) view
->buffer
.data
;
394 expected_size
= sizeof(*location_symbol_comm
) +
395 location_symbol_comm
->symbol_len
;
397 if (view
->buffer
.size
< expected_size
) {
398 ret
= -LTTNG_ERR_INVALID
;
402 symbol_name_src
= view
->buffer
.data
+ sizeof(*location_symbol_comm
);
404 if (!lttng_buffer_view_contains_string(&view
->buffer
, symbol_name_src
,
405 location_symbol_comm
->symbol_len
)) {
406 ret
= -LTTNG_ERR_INVALID
;
410 *location
= lttng_kernel_probe_location_symbol_create(
411 symbol_name_src
, location_symbol_comm
->offset
);
413 ret
= -LTTNG_ERR_INVALID
;
417 ret
= (ssize_t
) expected_size
;
423 ssize_t
lttng_kernel_probe_location_address_create_from_payload(
424 struct lttng_payload_view
*view
,
425 struct lttng_kernel_probe_location
**location
)
427 struct lttng_kernel_probe_location_address_comm
*location_address_comm
;
429 size_t expected_size
;
431 LTTNG_ASSERT(location
);
433 expected_size
= sizeof(*location_address_comm
);
435 if (view
->buffer
.size
< expected_size
) {
436 ret
= -LTTNG_ERR_INVALID
;
440 location_address_comm
=
441 (typeof(location_address_comm
)) view
->buffer
.data
;
443 *location
= lttng_kernel_probe_location_address_create(location_address_comm
->address
);
445 ret
= -LTTNG_ERR_INVALID
;
449 ret
= (size_t) expected_size
;
454 ssize_t
lttng_kernel_probe_location_create_from_payload(
455 struct lttng_payload_view
*view
,
456 struct lttng_kernel_probe_location
**location
)
458 enum lttng_kernel_probe_location_type type
;
459 ssize_t consumed
= 0;
461 const struct lttng_kernel_probe_location_comm
*probe_location_comm
;
462 const struct lttng_payload_view probe_location_comm_view
=
463 lttng_payload_view_from_view(
464 view
, 0, sizeof(*probe_location_comm
));
467 LTTNG_ASSERT(location
);
469 if (!lttng_payload_view_is_valid(&probe_location_comm_view
)) {
470 ret
= -LTTNG_ERR_INVALID
;
474 probe_location_comm
= (typeof(probe_location_comm
)) probe_location_comm_view
.buffer
.data
;
475 type
= (enum lttng_kernel_probe_location_type
) probe_location_comm
->type
;
476 consumed
+= sizeof(*probe_location_comm
);
479 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
481 struct lttng_payload_view location_view
=
482 lttng_payload_view_from_view(
485 ret
= lttng_kernel_probe_location_symbol_create_from_payload(
486 &location_view
, location
);
489 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
491 struct lttng_payload_view location_view
=
492 lttng_payload_view_from_view(view
, consumed
, -1);
494 ret
= lttng_kernel_probe_location_address_create_from_payload(
495 &location_view
, location
);
499 ret
= -LTTNG_ERR_INVALID
;
504 ret
= -LTTNG_ERR_INVALID
;
515 unsigned long lttng_kernel_probe_location_address_hash(
516 const struct lttng_kernel_probe_location
*location
)
518 unsigned long hash
= hash_key_ulong(
519 (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
,
521 struct lttng_kernel_probe_location_address
*address_location
=
522 container_of(location
, typeof(*address_location
),
525 hash
^= hash_key_u64(&address_location
->address
, lttng_ht_seed
);
531 bool lttng_kernel_probe_location_address_is_equal(
532 const struct lttng_kernel_probe_location
*_a
,
533 const struct lttng_kernel_probe_location
*_b
)
535 bool is_equal
= false;
536 struct lttng_kernel_probe_location_address
*a
, *b
;
538 a
= container_of(_a
, struct lttng_kernel_probe_location_address
,
540 b
= container_of(_b
, struct lttng_kernel_probe_location_address
,
543 if (a
->address
!= b
->address
) {
554 unsigned long lttng_kernel_probe_location_symbol_hash(
555 const struct lttng_kernel_probe_location
*location
)
557 unsigned long hash
= hash_key_ulong(
558 (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
,
560 struct lttng_kernel_probe_location_symbol
*symbol_location
=
561 container_of(location
, typeof(*symbol_location
),
564 hash
^= hash_key_str(symbol_location
->symbol_name
, lttng_ht_seed
);
565 hash
^= hash_key_u64(&symbol_location
->offset
, lttng_ht_seed
);
571 bool lttng_kernel_probe_location_symbol_is_equal(
572 const struct lttng_kernel_probe_location
*_a
,
573 const struct lttng_kernel_probe_location
*_b
)
575 bool is_equal
= false;
576 struct lttng_kernel_probe_location_symbol
*a
, *b
;
578 a
= container_of(_a
, struct lttng_kernel_probe_location_symbol
,
580 b
= container_of(_b
, struct lttng_kernel_probe_location_symbol
,
583 LTTNG_ASSERT(a
->symbol_name
);
584 LTTNG_ASSERT(b
->symbol_name
);
585 if (strcmp(a
->symbol_name
, b
->symbol_name
)) {
589 if (a
->offset
!= b
->offset
) {
599 bool lttng_kernel_probe_location_is_equal(
600 const struct lttng_kernel_probe_location
*a
,
601 const struct lttng_kernel_probe_location
*b
)
603 bool is_equal
= false;
614 if (a
->type
!= b
->type
) {
618 is_equal
= a
->equal
? a
->equal(a
, b
) : true;
623 static struct lttng_kernel_probe_location
*
624 lttng_kernel_probe_location_symbol_copy(
625 const struct lttng_kernel_probe_location
*location
)
627 struct lttng_kernel_probe_location
*new_location
= NULL
;
628 struct lttng_kernel_probe_location_symbol
*symbol_location
;
629 enum lttng_kernel_probe_location_status status
;
630 const char *symbol_name
= NULL
;
633 LTTNG_ASSERT(location
);
634 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
635 symbol_location
= container_of(
636 location
, typeof(*symbol_location
), parent
);
638 /* Get probe location offset */
639 status
= lttng_kernel_probe_location_symbol_get_offset(location
, &offset
);
640 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
641 ERR("Get kernel probe location offset failed.");
645 symbol_name
= lttng_kernel_probe_location_symbol_get_name(location
);
647 ERR("Kernel probe symbol name is NULL.");
651 /* Create the probe_location */
652 new_location
= lttng_kernel_probe_location_symbol_create(
653 symbol_name
, offset
);
662 static struct lttng_kernel_probe_location
*
663 lttng_kernel_probe_location_address_copy(
664 const struct lttng_kernel_probe_location
*location
)
666 struct lttng_kernel_probe_location
*new_location
= NULL
;
667 struct lttng_kernel_probe_location_address
*address_location
;
668 enum lttng_kernel_probe_location_status status
;
671 LTTNG_ASSERT(location
);
672 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
673 address_location
= container_of(
674 location
, typeof(*address_location
), parent
);
677 /* Get probe location fields */
678 status
= lttng_kernel_probe_location_address_get_address(location
, &address
);
679 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
680 ERR("Get kernel probe address failed.");
684 /* Create the probe_location */
685 new_location
= lttng_kernel_probe_location_address_create(address
);
695 struct lttng_kernel_probe_location
*lttng_kernel_probe_location_copy(
696 const struct lttng_kernel_probe_location
*location
)
698 struct lttng_kernel_probe_location
*new_location
= NULL
;
699 enum lttng_kernel_probe_location_type type
;
705 type
= lttng_kernel_probe_location_get_type(location
);
707 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
709 lttng_kernel_probe_location_address_copy(location
);
714 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
716 lttng_kernel_probe_location_symbol_copy(location
);
729 unsigned long lttng_kernel_probe_location_hash(
730 const struct lttng_kernel_probe_location
*location
)
732 return location
->hash(location
);
736 enum lttng_error_code
lttng_kernel_probe_location_address_mi_serialize(
737 const struct lttng_kernel_probe_location
*location
,
738 struct mi_writer
*writer
)
741 enum lttng_error_code ret_code
;
742 enum lttng_kernel_probe_location_status status
;
745 LTTNG_ASSERT(location
);
746 LTTNG_ASSERT(writer
);
747 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
749 status
= lttng_kernel_probe_location_address_get_address(
751 LTTNG_ASSERT(status
== LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
);
753 /* Open kernel probe location address element. */
754 ret
= mi_lttng_writer_open_element(
755 writer
, mi_lttng_element_kernel_probe_location_address
);
760 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
761 mi_lttng_element_kernel_probe_location_address_address
,
767 /* Close kernel probe location address element. */
768 ret
= mi_lttng_writer_close_element(writer
);
777 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
783 enum lttng_error_code
lttng_kernel_probe_location_symbol_mi_serialize(
784 const struct lttng_kernel_probe_location
*location
,
785 struct mi_writer
*writer
)
788 enum lttng_error_code ret_code
;
789 enum lttng_kernel_probe_location_status status
;
790 const char *name
= NULL
;
793 LTTNG_ASSERT(location
);
794 LTTNG_ASSERT(writer
);
795 LTTNG_ASSERT(location
->type
==
796 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
798 name
= lttng_kernel_probe_location_symbol_get_name(location
);
801 status
= lttng_kernel_probe_location_symbol_get_offset(
803 LTTNG_ASSERT(status
== LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
);
805 /* Open kernel probe location symbol offset element. */
806 ret
= mi_lttng_writer_open_element(writer
,
807 mi_lttng_element_kernel_probe_location_symbol_offset
);
813 ret
= mi_lttng_writer_write_element_string(writer
,
814 mi_lttng_element_kernel_probe_location_symbol_offset_name
,
821 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
822 mi_lttng_element_kernel_probe_location_symbol_offset_offset
,
828 /* Close kernel probe location symbol offset element. */
829 ret
= mi_lttng_writer_close_element(writer
);
838 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
843 enum lttng_error_code
lttng_kernel_probe_location_mi_serialize(
844 const struct lttng_kernel_probe_location
*location
,
845 struct mi_writer
*writer
)
848 enum lttng_error_code ret_code
;
850 LTTNG_ASSERT(location
);
851 LTTNG_ASSERT(writer
);
853 /* Open kernel probe location element. */
854 ret
= mi_lttng_writer_open_element(
855 writer
, mi_lttng_element_kernel_probe_location
);
860 /* Serialize the location sub type. */
861 ret_code
= location
->mi_serialize(location
, writer
);
862 if (ret_code
!= LTTNG_OK
) {
866 /* Close kernel probe location element. */
867 ret
= mi_lttng_writer_close_element(writer
);
876 ret_code
= LTTNG_ERR_MI_IO_FAIL
;