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
= lttng::utils::container_of(location
,
86 <tng_kernel_probe_location_symbol::parent
);
88 LTTNG_ASSERT(location_symbol
);
90 free(location_symbol
->symbol_name
);
94 void lttng_kernel_probe_location_destroy(
95 struct lttng_kernel_probe_location
*location
)
101 switch (location
->type
) {
102 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
103 lttng_kernel_probe_location_address_destroy(location
);
105 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
106 lttng_kernel_probe_location_symbol_destroy(location
);
113 struct lttng_kernel_probe_location
*
114 lttng_kernel_probe_location_address_create(uint64_t address
)
116 struct lttng_kernel_probe_location
*ret
= NULL
;
117 struct lttng_kernel_probe_location_address
*location
;
119 location
= zmalloc
<lttng_kernel_probe_location_address
>();
121 PERROR("Error allocating userspace probe location.");
125 location
->address
= address
;
127 ret
= &location
->parent
;
128 ret
->type
= LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
;
129 ret
->equal
= lttng_kernel_probe_location_address_is_equal
;
130 ret
->serialize
= lttng_kernel_probe_location_address_serialize
;
131 ret
->hash
= lttng_kernel_probe_location_address_hash
;
132 ret
->mi_serialize
= lttng_kernel_probe_location_address_mi_serialize
;
138 struct lttng_kernel_probe_location
*
139 lttng_kernel_probe_location_symbol_create(const char *symbol_name
,
142 char *symbol_name_copy
= NULL
;
143 struct lttng_kernel_probe_location
*ret
= NULL
;
144 struct lttng_kernel_probe_location_symbol
*location
;
146 if (!symbol_name
|| strlen(symbol_name
) >= LTTNG_SYMBOL_NAME_LEN
) {
150 symbol_name_copy
= strdup(symbol_name
);
151 if (!symbol_name_copy
) {
152 PERROR("Failed to copy symbol name '%s'", symbol_name
);
156 location
= zmalloc
<lttng_kernel_probe_location_symbol
>();
158 PERROR("Failed to allocate kernel symbol probe location");
162 location
->symbol_name
= symbol_name_copy
;
163 location
->offset
= offset
;
165 ret
= &location
->parent
;
166 ret
->type
= LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
;
167 ret
->equal
= lttng_kernel_probe_location_symbol_is_equal
;
168 ret
->serialize
= lttng_kernel_probe_location_symbol_serialize
;
169 ret
->hash
= lttng_kernel_probe_location_symbol_hash
;
170 ret
->mi_serialize
= lttng_kernel_probe_location_symbol_mi_serialize
;
174 free(symbol_name_copy
);
179 enum lttng_kernel_probe_location_status
180 lttng_kernel_probe_location_address_get_address(
181 const struct lttng_kernel_probe_location
*location
,
184 enum lttng_kernel_probe_location_status ret
=
185 LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
;
186 struct lttng_kernel_probe_location_address
*address_location
;
188 LTTNG_ASSERT(offset
);
190 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
191 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
) {
192 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
193 ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID
;
197 address_location
= lttng::utils::container_of(location
,
198 <tng_kernel_probe_location_address::parent
);
199 *offset
= address_location
->address
;
204 const char *lttng_kernel_probe_location_symbol_get_name(
205 const struct lttng_kernel_probe_location
*location
)
207 const char *ret
= NULL
;
208 struct lttng_kernel_probe_location_symbol
*symbol_location
;
210 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
211 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
) {
212 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
216 symbol_location
= lttng::utils::container_of(location
,
217 <tng_kernel_probe_location_symbol::parent
);
218 ret
= symbol_location
->symbol_name
;
223 enum lttng_kernel_probe_location_status
224 lttng_kernel_probe_location_symbol_get_offset(
225 const struct lttng_kernel_probe_location
*location
,
228 enum lttng_kernel_probe_location_status ret
=
229 LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
;
230 struct lttng_kernel_probe_location_symbol
*symbol_location
;
232 LTTNG_ASSERT(offset
);
234 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
235 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
) {
236 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
237 ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID
;
241 symbol_location
= lttng::utils::container_of(location
,
242 <tng_kernel_probe_location_symbol::parent
);
243 *offset
= symbol_location
->offset
;
249 int lttng_kernel_probe_location_symbol_serialize(
250 const struct lttng_kernel_probe_location
*location
,
251 struct lttng_payload
*payload
)
254 size_t symbol_name_len
;
255 size_t original_payload_size
;
256 struct lttng_kernel_probe_location_symbol
*location_symbol
;
257 struct lttng_kernel_probe_location_symbol_comm location_symbol_comm
;
259 if (!location
|| !payload
) {
260 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
261 ret
= -LTTNG_ERR_INVALID
;
265 LTTNG_ASSERT(lttng_kernel_probe_location_get_type(location
) ==
266 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
268 original_payload_size
= payload
->buffer
.size
;
269 location_symbol
= lttng::utils::container_of(location
,
270 <tng_kernel_probe_location_symbol::parent
);
272 if (!location_symbol
->symbol_name
) {
273 ret
= -LTTNG_ERR_INVALID
;
277 symbol_name_len
= strlen(location_symbol
->symbol_name
);
278 if (symbol_name_len
== 0) {
279 ret
= -LTTNG_ERR_INVALID
;
283 location_symbol_comm
.symbol_len
= symbol_name_len
+ 1;
284 location_symbol_comm
.offset
= location_symbol
->offset
;
286 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
287 &location_symbol_comm
, sizeof(location_symbol_comm
));
289 ret
= -LTTNG_ERR_INVALID
;
293 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
294 location_symbol
->symbol_name
,
295 location_symbol_comm
.symbol_len
);
297 ret
= -LTTNG_ERR_INVALID
;
301 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
307 int lttng_kernel_probe_location_address_serialize(
308 const struct lttng_kernel_probe_location
*location
,
309 struct lttng_payload
*payload
)
312 size_t original_payload_size
;
313 struct lttng_kernel_probe_location_address
*location_address
;
314 struct lttng_kernel_probe_location_address_comm location_address_comm
;
316 LTTNG_ASSERT(location
);
317 LTTNG_ASSERT(lttng_kernel_probe_location_get_type(location
) ==
318 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
320 original_payload_size
= payload
->buffer
.size
;
321 location_address
= lttng::utils::container_of(location
,
322 <tng_kernel_probe_location_address::parent
);
324 location_address_comm
.address
= location_address
->address
;
326 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
327 &location_address_comm
,
328 sizeof(location_address_comm
));
330 ret
= -LTTNG_ERR_INVALID
;
334 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
339 int lttng_kernel_probe_location_serialize(
340 const struct lttng_kernel_probe_location
*location
,
341 struct lttng_payload
*payload
)
344 size_t original_payload_size
;
345 struct lttng_kernel_probe_location_comm location_generic_comm
= {};
347 if (!location
|| !payload
) {
348 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
349 ret
= -LTTNG_ERR_INVALID
;
353 original_payload_size
= payload
->buffer
.size
;
354 location_generic_comm
.type
= (int8_t) location
->type
;
355 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
356 &location_generic_comm
,
357 sizeof(location_generic_comm
));
362 ret
= location
->serialize(location
, payload
);
367 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
373 int lttng_kernel_probe_location_symbol_create_from_payload(
374 struct lttng_payload_view
*view
,
375 struct lttng_kernel_probe_location
**location
)
377 struct lttng_kernel_probe_location_symbol_comm
*location_symbol_comm
;
378 const char *symbol_name_src
;
380 size_t expected_size
;
382 LTTNG_ASSERT(location
);
384 if (view
->buffer
.size
< sizeof(*location_symbol_comm
)) {
385 ret
= -LTTNG_ERR_INVALID
;
389 location_symbol_comm
=
390 (typeof(location_symbol_comm
)) view
->buffer
.data
;
392 expected_size
= sizeof(*location_symbol_comm
) +
393 location_symbol_comm
->symbol_len
;
395 if (view
->buffer
.size
< expected_size
) {
396 ret
= -LTTNG_ERR_INVALID
;
400 symbol_name_src
= view
->buffer
.data
+ sizeof(*location_symbol_comm
);
402 if (!lttng_buffer_view_contains_string(&view
->buffer
, symbol_name_src
,
403 location_symbol_comm
->symbol_len
)) {
404 ret
= -LTTNG_ERR_INVALID
;
408 *location
= lttng_kernel_probe_location_symbol_create(
409 symbol_name_src
, location_symbol_comm
->offset
);
411 ret
= -LTTNG_ERR_INVALID
;
415 ret
= (ssize_t
) expected_size
;
421 ssize_t
lttng_kernel_probe_location_address_create_from_payload(
422 struct lttng_payload_view
*view
,
423 struct lttng_kernel_probe_location
**location
)
425 struct lttng_kernel_probe_location_address_comm
*location_address_comm
;
427 size_t expected_size
;
429 LTTNG_ASSERT(location
);
431 expected_size
= sizeof(*location_address_comm
);
433 if (view
->buffer
.size
< expected_size
) {
434 ret
= -LTTNG_ERR_INVALID
;
438 location_address_comm
=
439 (typeof(location_address_comm
)) view
->buffer
.data
;
441 *location
= lttng_kernel_probe_location_address_create(location_address_comm
->address
);
443 ret
= -LTTNG_ERR_INVALID
;
447 ret
= (size_t) expected_size
;
452 ssize_t
lttng_kernel_probe_location_create_from_payload(
453 struct lttng_payload_view
*view
,
454 struct lttng_kernel_probe_location
**location
)
456 enum lttng_kernel_probe_location_type type
;
457 ssize_t consumed
= 0;
459 const struct lttng_kernel_probe_location_comm
*probe_location_comm
;
460 const struct lttng_payload_view probe_location_comm_view
=
461 lttng_payload_view_from_view(
462 view
, 0, sizeof(*probe_location_comm
));
465 LTTNG_ASSERT(location
);
467 if (!lttng_payload_view_is_valid(&probe_location_comm_view
)) {
468 ret
= -LTTNG_ERR_INVALID
;
472 probe_location_comm
= (typeof(probe_location_comm
)) probe_location_comm_view
.buffer
.data
;
473 type
= (enum lttng_kernel_probe_location_type
) probe_location_comm
->type
;
474 consumed
+= sizeof(*probe_location_comm
);
477 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
479 struct lttng_payload_view location_view
=
480 lttng_payload_view_from_view(
483 ret
= lttng_kernel_probe_location_symbol_create_from_payload(
484 &location_view
, location
);
487 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
489 struct lttng_payload_view location_view
=
490 lttng_payload_view_from_view(view
, consumed
, -1);
492 ret
= lttng_kernel_probe_location_address_create_from_payload(
493 &location_view
, location
);
497 ret
= -LTTNG_ERR_INVALID
;
502 ret
= -LTTNG_ERR_INVALID
;
513 unsigned long lttng_kernel_probe_location_address_hash(
514 const struct lttng_kernel_probe_location
*location
)
516 unsigned long hash
= hash_key_ulong(
517 (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
,
519 struct lttng_kernel_probe_location_address
*address_location
= lttng::utils::container_of(
520 location
, <tng_kernel_probe_location_address::parent
);
522 hash
^= hash_key_u64(&address_location
->address
, lttng_ht_seed
);
528 bool lttng_kernel_probe_location_address_is_equal(
529 const struct lttng_kernel_probe_location
*_a
,
530 const struct lttng_kernel_probe_location
*_b
)
532 bool is_equal
= false;
533 struct lttng_kernel_probe_location_address
*a
, *b
;
535 a
= lttng::utils::container_of(_a
, <tng_kernel_probe_location_address::parent
);
536 b
= lttng::utils::container_of(_b
, <tng_kernel_probe_location_address::parent
);
538 if (a
->address
!= b
->address
) {
549 unsigned long lttng_kernel_probe_location_symbol_hash(
550 const struct lttng_kernel_probe_location
*location
)
552 unsigned long hash
= hash_key_ulong(
553 (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
, lttng_ht_seed
);
554 struct lttng_kernel_probe_location_symbol
*symbol_location
= lttng::utils::container_of(
555 location
, <tng_kernel_probe_location_symbol::parent
);
557 hash
^= hash_key_str(symbol_location
->symbol_name
, lttng_ht_seed
);
558 hash
^= hash_key_u64(&symbol_location
->offset
, lttng_ht_seed
);
564 bool lttng_kernel_probe_location_symbol_is_equal(
565 const struct lttng_kernel_probe_location
*_a
,
566 const struct lttng_kernel_probe_location
*_b
)
568 bool is_equal
= false;
569 struct lttng_kernel_probe_location_symbol
*a
, *b
;
571 a
= lttng::utils::container_of(_a
,
572 <tng_kernel_probe_location_symbol::parent
);
573 b
= lttng::utils::container_of(_b
,
574 <tng_kernel_probe_location_symbol::parent
);
576 LTTNG_ASSERT(a
->symbol_name
);
577 LTTNG_ASSERT(b
->symbol_name
);
578 if (strcmp(a
->symbol_name
, b
->symbol_name
)) {
582 if (a
->offset
!= b
->offset
) {
592 bool lttng_kernel_probe_location_is_equal(
593 const struct lttng_kernel_probe_location
*a
,
594 const struct lttng_kernel_probe_location
*b
)
596 bool is_equal
= false;
607 if (a
->type
!= b
->type
) {
611 is_equal
= a
->equal
? a
->equal(a
, b
) : true;
616 static struct lttng_kernel_probe_location
*
617 lttng_kernel_probe_location_symbol_copy(
618 const struct lttng_kernel_probe_location
*location
)
620 struct lttng_kernel_probe_location
*new_location
= NULL
;
621 enum lttng_kernel_probe_location_status status
;
622 const char *symbol_name
= NULL
;
625 LTTNG_ASSERT(location
);
626 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
628 /* Get probe location offset */
629 status
= lttng_kernel_probe_location_symbol_get_offset(location
, &offset
);
630 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
631 ERR("Get kernel probe location offset failed.");
635 symbol_name
= lttng_kernel_probe_location_symbol_get_name(location
);
637 ERR("Kernel probe symbol name is NULL.");
641 /* Create the probe_location */
642 new_location
= lttng_kernel_probe_location_symbol_create(
643 symbol_name
, offset
);
652 static struct lttng_kernel_probe_location
*
653 lttng_kernel_probe_location_address_copy(
654 const struct lttng_kernel_probe_location
*location
)
656 struct lttng_kernel_probe_location
*new_location
= NULL
;
657 enum lttng_kernel_probe_location_status status
;
660 LTTNG_ASSERT(location
);
661 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
663 /* Get probe location fields */
664 status
= lttng_kernel_probe_location_address_get_address(location
, &address
);
665 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
666 ERR("Get kernel probe address failed.");
670 /* Create the probe_location */
671 new_location
= lttng_kernel_probe_location_address_create(address
);
681 struct lttng_kernel_probe_location
*lttng_kernel_probe_location_copy(
682 const struct lttng_kernel_probe_location
*location
)
684 struct lttng_kernel_probe_location
*new_location
= NULL
;
685 enum lttng_kernel_probe_location_type type
;
691 type
= lttng_kernel_probe_location_get_type(location
);
693 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
695 lttng_kernel_probe_location_address_copy(location
);
700 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
702 lttng_kernel_probe_location_symbol_copy(location
);
715 unsigned long lttng_kernel_probe_location_hash(
716 const struct lttng_kernel_probe_location
*location
)
718 return location
->hash(location
);
722 enum lttng_error_code
lttng_kernel_probe_location_address_mi_serialize(
723 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
;
731 LTTNG_ASSERT(location
);
732 LTTNG_ASSERT(writer
);
733 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
735 status
= lttng_kernel_probe_location_address_get_address(
737 LTTNG_ASSERT(status
== LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
);
739 /* Open kernel probe location address element. */
740 ret
= mi_lttng_writer_open_element(
741 writer
, mi_lttng_element_kernel_probe_location_address
);
746 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
747 mi_lttng_element_kernel_probe_location_address_address
,
753 /* Close kernel probe location address element. */
754 ret
= mi_lttng_writer_close_element(writer
);
763 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
769 enum lttng_error_code
lttng_kernel_probe_location_symbol_mi_serialize(
770 const struct lttng_kernel_probe_location
*location
,
771 struct mi_writer
*writer
)
774 enum lttng_error_code ret_code
;
775 enum lttng_kernel_probe_location_status status
;
776 const char *name
= NULL
;
779 LTTNG_ASSERT(location
);
780 LTTNG_ASSERT(writer
);
781 LTTNG_ASSERT(location
->type
==
782 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
784 name
= lttng_kernel_probe_location_symbol_get_name(location
);
787 status
= lttng_kernel_probe_location_symbol_get_offset(
789 LTTNG_ASSERT(status
== LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
);
791 /* Open kernel probe location symbol offset element. */
792 ret
= mi_lttng_writer_open_element(writer
,
793 mi_lttng_element_kernel_probe_location_symbol_offset
);
799 ret
= mi_lttng_writer_write_element_string(writer
,
800 mi_lttng_element_kernel_probe_location_symbol_offset_name
,
807 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
808 mi_lttng_element_kernel_probe_location_symbol_offset_offset
,
814 /* Close kernel probe location symbol offset element. */
815 ret
= mi_lttng_writer_close_element(writer
);
824 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
829 enum lttng_error_code
lttng_kernel_probe_location_mi_serialize(
830 const struct lttng_kernel_probe_location
*location
,
831 struct mi_writer
*writer
)
834 enum lttng_error_code ret_code
;
836 LTTNG_ASSERT(location
);
837 LTTNG_ASSERT(writer
);
839 /* Open kernel probe location element. */
840 ret
= mi_lttng_writer_open_element(
841 writer
, mi_lttng_element_kernel_probe_location
);
846 /* Serialize the location sub type. */
847 ret_code
= location
->mi_serialize(location
, writer
);
848 if (ret_code
!= LTTNG_OK
) {
852 /* Close kernel probe location element. */
853 ret
= mi_lttng_writer_close_element(writer
);
862 ret_code
= LTTNG_ERR_MI_IO_FAIL
;