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.hpp>
11 #include <common/hashtable/hashtable.hpp>
12 #include <common/hashtable/utils.hpp>
13 #include <common/macros.hpp>
14 #include <common/mi-lttng.hpp>
15 #include <common/payload-view.hpp>
16 #include <common/payload.hpp>
18 #include <lttng/constant.h>
19 #include <lttng/kernel-probe-internal.hpp>
20 #include <lttng/kernel-probe.h>
24 #include <sys/types.h>
28 lttng_kernel_probe_location_address_serialize(const struct lttng_kernel_probe_location
*location
,
29 struct lttng_payload
*payload
);
32 lttng_kernel_probe_location_symbol_serialize(const struct lttng_kernel_probe_location
*location
,
33 struct lttng_payload
*payload
);
36 lttng_kernel_probe_location_address_is_equal(const struct lttng_kernel_probe_location
*a
,
37 const struct lttng_kernel_probe_location
*b
);
40 lttng_kernel_probe_location_symbol_is_equal(const struct lttng_kernel_probe_location
*a
,
41 const struct lttng_kernel_probe_location
*b
);
44 lttng_kernel_probe_location_address_hash(const struct lttng_kernel_probe_location
*location
);
47 lttng_kernel_probe_location_symbol_hash(const struct lttng_kernel_probe_location
*location
);
49 static enum lttng_error_code
50 lttng_kernel_probe_location_address_mi_serialize(const struct lttng_kernel_probe_location
*location
,
51 struct mi_writer
*writer
);
53 static enum lttng_error_code
54 lttng_kernel_probe_location_symbol_mi_serialize(const struct lttng_kernel_probe_location
*location
,
55 struct mi_writer
*writer
);
57 enum lttng_kernel_probe_location_type
58 lttng_kernel_probe_location_get_type(const struct lttng_kernel_probe_location
*location
)
60 return location
? location
->type
: LTTNG_KERNEL_PROBE_LOCATION_TYPE_UNKNOWN
;
64 lttng_kernel_probe_location_address_destroy(struct lttng_kernel_probe_location
*location
)
66 LTTNG_ASSERT(location
);
70 static void lttng_kernel_probe_location_symbol_destroy(struct lttng_kernel_probe_location
*location
)
72 struct lttng_kernel_probe_location_symbol
*location_symbol
= nullptr;
74 LTTNG_ASSERT(location
);
77 lttng::utils::container_of(location
, <tng_kernel_probe_location_symbol::parent
);
79 LTTNG_ASSERT(location_symbol
);
81 free(location_symbol
->symbol_name
);
85 void lttng_kernel_probe_location_destroy(struct lttng_kernel_probe_location
*location
)
91 switch (location
->type
) {
92 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
93 lttng_kernel_probe_location_address_destroy(location
);
95 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
96 lttng_kernel_probe_location_symbol_destroy(location
);
103 struct lttng_kernel_probe_location
*lttng_kernel_probe_location_address_create(uint64_t address
)
105 struct lttng_kernel_probe_location
*ret
= nullptr;
106 struct lttng_kernel_probe_location_address
*location
;
108 location
= zmalloc
<lttng_kernel_probe_location_address
>();
110 PERROR("Error allocating userspace probe location.");
114 location
->address
= address
;
116 ret
= &location
->parent
;
117 ret
->type
= LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
;
118 ret
->equal
= lttng_kernel_probe_location_address_is_equal
;
119 ret
->serialize
= lttng_kernel_probe_location_address_serialize
;
120 ret
->hash
= lttng_kernel_probe_location_address_hash
;
121 ret
->mi_serialize
= lttng_kernel_probe_location_address_mi_serialize
;
127 struct lttng_kernel_probe_location
*
128 lttng_kernel_probe_location_symbol_create(const char *symbol_name
, uint64_t offset
)
130 char *symbol_name_copy
= nullptr;
131 struct lttng_kernel_probe_location
*ret
= nullptr;
132 struct lttng_kernel_probe_location_symbol
*location
;
134 if (!symbol_name
|| strlen(symbol_name
) >= LTTNG_SYMBOL_NAME_LEN
) {
138 symbol_name_copy
= strdup(symbol_name
);
139 if (!symbol_name_copy
) {
140 PERROR("Failed to copy symbol name '%s'", symbol_name
);
144 location
= zmalloc
<lttng_kernel_probe_location_symbol
>();
146 PERROR("Failed to allocate kernel symbol probe location");
150 location
->symbol_name
= symbol_name_copy
;
151 location
->offset
= offset
;
153 ret
= &location
->parent
;
154 ret
->type
= LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
;
155 ret
->equal
= lttng_kernel_probe_location_symbol_is_equal
;
156 ret
->serialize
= lttng_kernel_probe_location_symbol_serialize
;
157 ret
->hash
= lttng_kernel_probe_location_symbol_hash
;
158 ret
->mi_serialize
= lttng_kernel_probe_location_symbol_mi_serialize
;
162 free(symbol_name_copy
);
167 enum lttng_kernel_probe_location_status
168 lttng_kernel_probe_location_address_get_address(const struct lttng_kernel_probe_location
*location
,
171 enum lttng_kernel_probe_location_status ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
;
172 struct lttng_kernel_probe_location_address
*address_location
;
174 LTTNG_ASSERT(offset
);
177 lttng_kernel_probe_location_get_type(location
) !=
178 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
) {
179 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
180 ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID
;
185 lttng::utils::container_of(location
, <tng_kernel_probe_location_address::parent
);
186 *offset
= address_location
->address
;
192 lttng_kernel_probe_location_symbol_get_name(const struct lttng_kernel_probe_location
*location
)
194 const char *ret
= nullptr;
195 struct lttng_kernel_probe_location_symbol
*symbol_location
;
198 lttng_kernel_probe_location_get_type(location
) !=
199 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
) {
200 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
205 lttng::utils::container_of(location
, <tng_kernel_probe_location_symbol::parent
);
206 ret
= symbol_location
->symbol_name
;
211 enum lttng_kernel_probe_location_status
212 lttng_kernel_probe_location_symbol_get_offset(const struct lttng_kernel_probe_location
*location
,
215 enum lttng_kernel_probe_location_status ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
;
216 struct lttng_kernel_probe_location_symbol
*symbol_location
;
218 LTTNG_ASSERT(offset
);
221 lttng_kernel_probe_location_get_type(location
) !=
222 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
) {
223 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
224 ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID
;
229 lttng::utils::container_of(location
, <tng_kernel_probe_location_symbol::parent
);
230 *offset
= symbol_location
->offset
;
236 lttng_kernel_probe_location_symbol_serialize(const struct lttng_kernel_probe_location
*location
,
237 struct lttng_payload
*payload
)
240 size_t symbol_name_len
;
241 size_t original_payload_size
;
242 struct lttng_kernel_probe_location_symbol
*location_symbol
;
243 struct lttng_kernel_probe_location_symbol_comm location_symbol_comm
;
245 if (!location
|| !payload
) {
246 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
247 ret
= -LTTNG_ERR_INVALID
;
251 LTTNG_ASSERT(lttng_kernel_probe_location_get_type(location
) ==
252 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
254 original_payload_size
= payload
->buffer
.size
;
256 lttng::utils::container_of(location
, <tng_kernel_probe_location_symbol::parent
);
258 if (!location_symbol
->symbol_name
) {
259 ret
= -LTTNG_ERR_INVALID
;
263 symbol_name_len
= strlen(location_symbol
->symbol_name
);
264 if (symbol_name_len
== 0) {
265 ret
= -LTTNG_ERR_INVALID
;
269 location_symbol_comm
.symbol_len
= symbol_name_len
+ 1;
270 location_symbol_comm
.offset
= location_symbol
->offset
;
272 ret
= lttng_dynamic_buffer_append(
273 &payload
->buffer
, &location_symbol_comm
, sizeof(location_symbol_comm
));
275 ret
= -LTTNG_ERR_INVALID
;
279 ret
= lttng_dynamic_buffer_append(
280 &payload
->buffer
, location_symbol
->symbol_name
, location_symbol_comm
.symbol_len
);
282 ret
= -LTTNG_ERR_INVALID
;
286 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
292 lttng_kernel_probe_location_address_serialize(const struct lttng_kernel_probe_location
*location
,
293 struct lttng_payload
*payload
)
296 size_t original_payload_size
;
297 struct lttng_kernel_probe_location_address
*location_address
;
298 struct lttng_kernel_probe_location_address_comm location_address_comm
;
300 LTTNG_ASSERT(location
);
301 LTTNG_ASSERT(lttng_kernel_probe_location_get_type(location
) ==
302 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
304 original_payload_size
= payload
->buffer
.size
;
306 lttng::utils::container_of(location
, <tng_kernel_probe_location_address::parent
);
308 location_address_comm
.address
= location_address
->address
;
310 ret
= lttng_dynamic_buffer_append(
311 &payload
->buffer
, &location_address_comm
, sizeof(location_address_comm
));
313 ret
= -LTTNG_ERR_INVALID
;
317 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
322 int lttng_kernel_probe_location_serialize(const struct lttng_kernel_probe_location
*location
,
323 struct lttng_payload
*payload
)
326 size_t original_payload_size
;
327 struct lttng_kernel_probe_location_comm location_generic_comm
= {};
329 if (!location
|| !payload
) {
330 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
331 ret
= -LTTNG_ERR_INVALID
;
335 original_payload_size
= payload
->buffer
.size
;
336 location_generic_comm
.type
= (int8_t) location
->type
;
337 ret
= lttng_dynamic_buffer_append(
338 &payload
->buffer
, &location_generic_comm
, sizeof(location_generic_comm
));
343 ret
= location
->serialize(location
, payload
);
348 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
353 static int lttng_kernel_probe_location_symbol_create_from_payload(
354 struct lttng_payload_view
*view
, 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
;
361 LTTNG_ASSERT(location
);
363 if (view
->buffer
.size
< sizeof(*location_symbol_comm
)) {
364 ret
= -LTTNG_ERR_INVALID
;
368 location_symbol_comm
= (typeof(location_symbol_comm
)) view
->buffer
.data
;
370 expected_size
= sizeof(*location_symbol_comm
) + location_symbol_comm
->symbol_len
;
372 if (view
->buffer
.size
< expected_size
) {
373 ret
= -LTTNG_ERR_INVALID
;
377 symbol_name_src
= view
->buffer
.data
+ sizeof(*location_symbol_comm
);
379 if (!lttng_buffer_view_contains_string(
380 &view
->buffer
, symbol_name_src
, location_symbol_comm
->symbol_len
)) {
381 ret
= -LTTNG_ERR_INVALID
;
385 *location
= lttng_kernel_probe_location_symbol_create(symbol_name_src
,
386 location_symbol_comm
->offset
);
388 ret
= -LTTNG_ERR_INVALID
;
392 ret
= (ssize_t
) expected_size
;
397 static ssize_t
lttng_kernel_probe_location_address_create_from_payload(
398 struct lttng_payload_view
*view
, struct lttng_kernel_probe_location
**location
)
400 struct lttng_kernel_probe_location_address_comm
*location_address_comm
;
402 size_t expected_size
;
404 LTTNG_ASSERT(location
);
406 expected_size
= sizeof(*location_address_comm
);
408 if (view
->buffer
.size
< expected_size
) {
409 ret
= -LTTNG_ERR_INVALID
;
413 location_address_comm
= (typeof(location_address_comm
)) view
->buffer
.data
;
415 *location
= lttng_kernel_probe_location_address_create(location_address_comm
->address
);
417 ret
= -LTTNG_ERR_INVALID
;
421 ret
= (size_t) expected_size
;
427 lttng_kernel_probe_location_create_from_payload(struct lttng_payload_view
*view
,
428 struct lttng_kernel_probe_location
**location
)
430 enum lttng_kernel_probe_location_type type
;
431 ssize_t consumed
= 0;
433 const struct lttng_kernel_probe_location_comm
*probe_location_comm
;
434 const struct lttng_payload_view probe_location_comm_view
=
435 lttng_payload_view_from_view(view
, 0, sizeof(*probe_location_comm
));
438 LTTNG_ASSERT(location
);
440 if (!lttng_payload_view_is_valid(&probe_location_comm_view
)) {
441 ret
= -LTTNG_ERR_INVALID
;
445 probe_location_comm
= (typeof(probe_location_comm
)) probe_location_comm_view
.buffer
.data
;
446 type
= (enum lttng_kernel_probe_location_type
) probe_location_comm
->type
;
447 consumed
+= sizeof(*probe_location_comm
);
450 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
452 struct lttng_payload_view location_view
=
453 lttng_payload_view_from_view(view
, consumed
, -1);
455 ret
= lttng_kernel_probe_location_symbol_create_from_payload(&location_view
,
459 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
461 struct lttng_payload_view location_view
=
462 lttng_payload_view_from_view(view
, consumed
, -1);
464 ret
= lttng_kernel_probe_location_address_create_from_payload(&location_view
,
469 ret
= -LTTNG_ERR_INVALID
;
474 ret
= -LTTNG_ERR_INVALID
;
485 lttng_kernel_probe_location_address_hash(const struct lttng_kernel_probe_location
*location
)
488 hash_key_ulong((void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
, lttng_ht_seed
);
489 struct lttng_kernel_probe_location_address
*address_location
=
490 lttng::utils::container_of(location
, <tng_kernel_probe_location_address::parent
);
492 hash
^= hash_key_u64(&address_location
->address
, lttng_ht_seed
);
498 lttng_kernel_probe_location_address_is_equal(const struct lttng_kernel_probe_location
*_a
,
499 const struct lttng_kernel_probe_location
*_b
)
501 bool is_equal
= false;
502 struct lttng_kernel_probe_location_address
*a
, *b
;
504 a
= lttng::utils::container_of(_a
, <tng_kernel_probe_location_address::parent
);
505 b
= lttng::utils::container_of(_b
, <tng_kernel_probe_location_address::parent
);
507 if (a
->address
!= b
->address
) {
518 lttng_kernel_probe_location_symbol_hash(const struct lttng_kernel_probe_location
*location
)
520 unsigned long hash
= hash_key_ulong((void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
,
522 struct lttng_kernel_probe_location_symbol
*symbol_location
=
523 lttng::utils::container_of(location
, <tng_kernel_probe_location_symbol::parent
);
525 hash
^= hash_key_str(symbol_location
->symbol_name
, lttng_ht_seed
);
526 hash
^= hash_key_u64(&symbol_location
->offset
, lttng_ht_seed
);
532 lttng_kernel_probe_location_symbol_is_equal(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_symbol
*a
, *b
;
538 a
= lttng::utils::container_of(_a
, <tng_kernel_probe_location_symbol::parent
);
539 b
= lttng::utils::container_of(_b
, <tng_kernel_probe_location_symbol::parent
);
541 LTTNG_ASSERT(a
->symbol_name
);
542 LTTNG_ASSERT(b
->symbol_name
);
543 if (strcmp(a
->symbol_name
, b
->symbol_name
) != 0) {
547 if (a
->offset
!= b
->offset
) {
557 bool lttng_kernel_probe_location_is_equal(const struct lttng_kernel_probe_location
*a
,
558 const struct lttng_kernel_probe_location
*b
)
560 bool is_equal
= false;
571 if (a
->type
!= b
->type
) {
575 is_equal
= a
->equal
? a
->equal(a
, b
) : true;
580 static struct lttng_kernel_probe_location
*
581 lttng_kernel_probe_location_symbol_copy(const struct lttng_kernel_probe_location
*location
)
583 struct lttng_kernel_probe_location
*new_location
= nullptr;
584 enum lttng_kernel_probe_location_status status
;
585 const char *symbol_name
= nullptr;
588 LTTNG_ASSERT(location
);
589 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
591 /* Get probe location offset */
592 status
= lttng_kernel_probe_location_symbol_get_offset(location
, &offset
);
593 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
594 ERR("Get kernel probe location offset failed.");
598 symbol_name
= lttng_kernel_probe_location_symbol_get_name(location
);
600 ERR("Kernel probe symbol name is NULL.");
604 /* Create the probe_location */
605 new_location
= lttng_kernel_probe_location_symbol_create(symbol_name
, offset
);
610 new_location
= nullptr;
614 static struct lttng_kernel_probe_location
*
615 lttng_kernel_probe_location_address_copy(const struct lttng_kernel_probe_location
*location
)
617 struct lttng_kernel_probe_location
*new_location
= nullptr;
618 enum lttng_kernel_probe_location_status status
;
621 LTTNG_ASSERT(location
);
622 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
624 /* Get probe location fields */
625 status
= lttng_kernel_probe_location_address_get_address(location
, &address
);
626 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
627 ERR("Get kernel probe address failed.");
631 /* Create the probe_location */
632 new_location
= lttng_kernel_probe_location_address_create(address
);
637 new_location
= nullptr;
642 struct lttng_kernel_probe_location
*
643 lttng_kernel_probe_location_copy(const struct lttng_kernel_probe_location
*location
)
645 struct lttng_kernel_probe_location
*new_location
= nullptr;
646 enum lttng_kernel_probe_location_type type
;
652 type
= lttng_kernel_probe_location_get_type(location
);
654 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
655 new_location
= lttng_kernel_probe_location_address_copy(location
);
660 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
661 new_location
= lttng_kernel_probe_location_symbol_copy(location
);
667 new_location
= nullptr;
674 unsigned long lttng_kernel_probe_location_hash(const struct lttng_kernel_probe_location
*location
)
676 return location
->hash(location
);
679 static enum lttng_error_code
680 lttng_kernel_probe_location_address_mi_serialize(const struct lttng_kernel_probe_location
*location
,
681 struct mi_writer
*writer
)
684 enum lttng_error_code ret_code
;
685 enum lttng_kernel_probe_location_status status
;
688 LTTNG_ASSERT(location
);
689 LTTNG_ASSERT(writer
);
690 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
692 status
= lttng_kernel_probe_location_address_get_address(location
, &address
);
693 LTTNG_ASSERT(status
== LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
);
695 /* Open kernel probe location address element. */
696 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_kernel_probe_location_address
);
701 ret
= mi_lttng_writer_write_element_unsigned_int(
702 writer
, mi_lttng_element_kernel_probe_location_address_address
, address
);
707 /* Close kernel probe location address element. */
708 ret
= mi_lttng_writer_close_element(writer
);
717 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
722 static enum lttng_error_code
723 lttng_kernel_probe_location_symbol_mi_serialize(const struct lttng_kernel_probe_location
*location
,
724 struct mi_writer
*writer
)
727 enum lttng_error_code ret_code
;
728 enum lttng_kernel_probe_location_status status
;
729 const char *name
= nullptr;
732 LTTNG_ASSERT(location
);
733 LTTNG_ASSERT(writer
);
734 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
736 name
= lttng_kernel_probe_location_symbol_get_name(location
);
739 status
= lttng_kernel_probe_location_symbol_get_offset(location
, &offset
);
740 LTTNG_ASSERT(status
== LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
);
742 /* Open kernel probe location symbol offset element. */
743 ret
= mi_lttng_writer_open_element(writer
,
744 mi_lttng_element_kernel_probe_location_symbol_offset
);
750 ret
= mi_lttng_writer_write_element_string(
751 writer
, mi_lttng_element_kernel_probe_location_symbol_offset_name
, name
);
757 ret
= mi_lttng_writer_write_element_unsigned_int(
758 writer
, mi_lttng_element_kernel_probe_location_symbol_offset_offset
, offset
);
763 /* Close kernel probe location symbol offset element. */
764 ret
= mi_lttng_writer_close_element(writer
);
773 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
778 enum lttng_error_code
779 lttng_kernel_probe_location_mi_serialize(const struct lttng_kernel_probe_location
*location
,
780 struct mi_writer
*writer
)
783 enum lttng_error_code ret_code
;
785 LTTNG_ASSERT(location
);
786 LTTNG_ASSERT(writer
);
788 /* Open kernel probe location element. */
789 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_kernel_probe_location
);
794 /* Serialize the location sub type. */
795 ret_code
= location
->mi_serialize(location
, writer
);
796 if (ret_code
!= LTTNG_OK
) {
800 /* Close kernel probe location element. */
801 ret
= mi_lttng_writer_close_element(writer
);
810 ret_code
= LTTNG_ERR_MI_IO_FAIL
;