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.h>
10 #include <common/hashtable/hashtable.h>
11 #include <common/hashtable/utils.h>
12 #include <common/macros.h>
13 #include <common/mi-lttng.h>
14 #include <common/payload-view.h>
15 #include <common/payload.h>
17 #include <lttng/constant.h>
18 #include <lttng/kernel-probe-internal.h>
19 #include <lttng/kernel-probe.h>
21 #include <sys/types.h>
22 #include <sys/unistd.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(sizeof(*location
));
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(sizeof(*location
));
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
);
342 int lttng_kernel_probe_location_serialize(
343 const struct lttng_kernel_probe_location
*location
,
344 struct lttng_payload
*payload
)
347 size_t original_payload_size
;
348 struct lttng_kernel_probe_location_comm location_generic_comm
= {};
350 if (!location
|| !payload
) {
351 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
352 ret
= -LTTNG_ERR_INVALID
;
356 original_payload_size
= payload
->buffer
.size
;
357 location_generic_comm
.type
= (int8_t) location
->type
;
358 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
359 &location_generic_comm
,
360 sizeof(location_generic_comm
));
365 ret
= location
->serialize(location
, payload
);
370 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
376 int lttng_kernel_probe_location_symbol_create_from_payload(
377 struct lttng_payload_view
*view
,
378 struct lttng_kernel_probe_location
**location
)
380 struct lttng_kernel_probe_location_symbol_comm
*location_symbol_comm
;
381 const char *symbol_name_src
;
383 size_t expected_size
;
385 LTTNG_ASSERT(location
);
387 if (view
->buffer
.size
< sizeof(*location_symbol_comm
)) {
388 ret
= -LTTNG_ERR_INVALID
;
392 location_symbol_comm
=
393 (typeof(location_symbol_comm
)) view
->buffer
.data
;
395 expected_size
= sizeof(*location_symbol_comm
) +
396 location_symbol_comm
->symbol_len
;
398 if (view
->buffer
.size
< expected_size
) {
399 ret
= -LTTNG_ERR_INVALID
;
403 symbol_name_src
= view
->buffer
.data
+ sizeof(*location_symbol_comm
);
405 if (!lttng_buffer_view_contains_string(&view
->buffer
, symbol_name_src
,
406 location_symbol_comm
->symbol_len
)) {
407 ret
= -LTTNG_ERR_INVALID
;
411 *location
= lttng_kernel_probe_location_symbol_create(
412 symbol_name_src
, location_symbol_comm
->offset
);
414 ret
= -LTTNG_ERR_INVALID
;
418 ret
= (ssize_t
) expected_size
;
424 ssize_t
lttng_kernel_probe_location_address_create_from_payload(
425 struct lttng_payload_view
*view
,
426 struct lttng_kernel_probe_location
**location
)
428 struct lttng_kernel_probe_location_address_comm
*location_address_comm
;
430 size_t expected_size
;
432 LTTNG_ASSERT(location
);
434 expected_size
= sizeof(*location_address_comm
);
436 if (view
->buffer
.size
< expected_size
) {
437 ret
= -LTTNG_ERR_INVALID
;
441 location_address_comm
=
442 (typeof(location_address_comm
)) view
->buffer
.data
;
444 *location
= lttng_kernel_probe_location_address_create(location_address_comm
->address
);
446 ret
= -LTTNG_ERR_INVALID
;
450 ret
= (size_t) expected_size
;
456 ssize_t
lttng_kernel_probe_location_create_from_payload(
457 struct lttng_payload_view
*view
,
458 struct lttng_kernel_probe_location
**location
)
460 enum lttng_kernel_probe_location_type type
;
461 ssize_t consumed
= 0;
463 const struct lttng_kernel_probe_location_comm
*probe_location_comm
;
464 const struct lttng_payload_view probe_location_comm_view
=
465 lttng_payload_view_from_view(
466 view
, 0, sizeof(*probe_location_comm
));
469 LTTNG_ASSERT(location
);
471 if (!lttng_payload_view_is_valid(&probe_location_comm_view
)) {
472 ret
= -LTTNG_ERR_INVALID
;
476 probe_location_comm
= (typeof(probe_location_comm
)) probe_location_comm_view
.buffer
.data
;
477 type
= (enum lttng_kernel_probe_location_type
) probe_location_comm
->type
;
478 consumed
+= sizeof(*probe_location_comm
);
481 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
483 struct lttng_payload_view location_view
=
484 lttng_payload_view_from_view(
487 ret
= lttng_kernel_probe_location_symbol_create_from_payload(
488 &location_view
, location
);
491 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
493 struct lttng_payload_view location_view
=
494 lttng_payload_view_from_view(view
, consumed
, -1);
496 ret
= lttng_kernel_probe_location_address_create_from_payload(
497 &location_view
, location
);
501 ret
= -LTTNG_ERR_INVALID
;
506 ret
= -LTTNG_ERR_INVALID
;
517 unsigned long lttng_kernel_probe_location_address_hash(
518 const struct lttng_kernel_probe_location
*location
)
520 unsigned long hash
= hash_key_ulong(
521 (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
,
523 struct lttng_kernel_probe_location_address
*address_location
=
524 container_of(location
, typeof(*address_location
),
527 hash
^= hash_key_u64(&address_location
->address
, lttng_ht_seed
);
533 bool lttng_kernel_probe_location_address_is_equal(
534 const struct lttng_kernel_probe_location
*_a
,
535 const struct lttng_kernel_probe_location
*_b
)
537 bool is_equal
= false;
538 struct lttng_kernel_probe_location_address
*a
, *b
;
540 a
= container_of(_a
, struct lttng_kernel_probe_location_address
,
542 b
= container_of(_b
, struct lttng_kernel_probe_location_address
,
545 if (a
->address
!= b
->address
) {
556 unsigned long lttng_kernel_probe_location_symbol_hash(
557 const struct lttng_kernel_probe_location
*location
)
559 unsigned long hash
= hash_key_ulong(
560 (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
,
562 struct lttng_kernel_probe_location_symbol
*symbol_location
=
563 container_of(location
, typeof(*symbol_location
),
566 hash
^= hash_key_str(symbol_location
->symbol_name
, lttng_ht_seed
);
567 hash
^= hash_key_u64(&symbol_location
->offset
, lttng_ht_seed
);
573 bool lttng_kernel_probe_location_symbol_is_equal(
574 const struct lttng_kernel_probe_location
*_a
,
575 const struct lttng_kernel_probe_location
*_b
)
577 bool is_equal
= false;
578 struct lttng_kernel_probe_location_symbol
*a
, *b
;
580 a
= container_of(_a
, struct lttng_kernel_probe_location_symbol
,
582 b
= container_of(_b
, struct lttng_kernel_probe_location_symbol
,
585 LTTNG_ASSERT(a
->symbol_name
);
586 LTTNG_ASSERT(b
->symbol_name
);
587 if (strcmp(a
->symbol_name
, b
->symbol_name
)) {
591 if (a
->offset
!= b
->offset
) {
602 bool lttng_kernel_probe_location_is_equal(
603 const struct lttng_kernel_probe_location
*a
,
604 const struct lttng_kernel_probe_location
*b
)
606 bool is_equal
= false;
617 if (a
->type
!= b
->type
) {
621 is_equal
= a
->equal
? a
->equal(a
, b
) : true;
626 static struct lttng_kernel_probe_location
*
627 lttng_kernel_probe_location_symbol_copy(
628 const struct lttng_kernel_probe_location
*location
)
630 struct lttng_kernel_probe_location
*new_location
= NULL
;
631 struct lttng_kernel_probe_location_symbol
*symbol_location
;
632 enum lttng_kernel_probe_location_status status
;
633 const char *symbol_name
= NULL
;
636 LTTNG_ASSERT(location
);
637 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
638 symbol_location
= container_of(
639 location
, typeof(*symbol_location
), parent
);
641 /* Get probe location offset */
642 status
= lttng_kernel_probe_location_symbol_get_offset(location
, &offset
);
643 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
644 ERR("Get kernel probe location offset failed.");
648 symbol_name
= lttng_kernel_probe_location_symbol_get_name(location
);
650 ERR("Kernel probe symbol name is NULL.");
654 /* Create the probe_location */
655 new_location
= lttng_kernel_probe_location_symbol_create(
656 symbol_name
, offset
);
665 static struct lttng_kernel_probe_location
*
666 lttng_kernel_probe_location_address_copy(
667 const struct lttng_kernel_probe_location
*location
)
669 struct lttng_kernel_probe_location
*new_location
= NULL
;
670 struct lttng_kernel_probe_location_address
*address_location
;
671 enum lttng_kernel_probe_location_status status
;
674 LTTNG_ASSERT(location
);
675 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
676 address_location
= container_of(
677 location
, typeof(*address_location
), parent
);
680 /* Get probe location fields */
681 status
= lttng_kernel_probe_location_address_get_address(location
, &address
);
682 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
683 ERR("Get kernel probe address failed.");
687 /* Create the probe_location */
688 new_location
= lttng_kernel_probe_location_address_create(address
);
699 struct lttng_kernel_probe_location
*lttng_kernel_probe_location_copy(
700 const struct lttng_kernel_probe_location
*location
)
702 struct lttng_kernel_probe_location
*new_location
= NULL
;
703 enum lttng_kernel_probe_location_type type
;
709 type
= lttng_kernel_probe_location_get_type(location
);
711 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
713 lttng_kernel_probe_location_address_copy(location
);
718 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
720 lttng_kernel_probe_location_symbol_copy(location
);
734 unsigned long lttng_kernel_probe_location_hash(
735 const struct lttng_kernel_probe_location
*location
)
737 return location
->hash(location
);
741 enum lttng_error_code
lttng_kernel_probe_location_address_mi_serialize(
742 const struct lttng_kernel_probe_location
*location
,
743 struct mi_writer
*writer
)
746 enum lttng_error_code ret_code
;
747 enum lttng_kernel_probe_location_status status
;
750 LTTNG_ASSERT(location
);
751 LTTNG_ASSERT(writer
);
752 LTTNG_ASSERT(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
754 status
= lttng_kernel_probe_location_address_get_address(
756 LTTNG_ASSERT(status
== LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
);
758 /* Open kernel probe location address element. */
759 ret
= mi_lttng_writer_open_element(
760 writer
, mi_lttng_element_kernel_probe_location_address
);
765 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
766 mi_lttng_element_kernel_probe_location_address_address
,
772 /* Close kernel probe location address element. */
773 ret
= mi_lttng_writer_close_element(writer
);
782 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
788 enum lttng_error_code
lttng_kernel_probe_location_symbol_mi_serialize(
789 const struct lttng_kernel_probe_location
*location
,
790 struct mi_writer
*writer
)
793 enum lttng_error_code ret_code
;
794 enum lttng_kernel_probe_location_status status
;
795 const char *name
= NULL
;
798 LTTNG_ASSERT(location
);
799 LTTNG_ASSERT(writer
);
800 LTTNG_ASSERT(location
->type
==
801 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
803 name
= lttng_kernel_probe_location_symbol_get_name(location
);
806 status
= lttng_kernel_probe_location_symbol_get_offset(
808 LTTNG_ASSERT(status
== LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
);
810 /* Open kernel probe location symbol offset element. */
811 ret
= mi_lttng_writer_open_element(writer
,
812 mi_lttng_element_kernel_probe_location_symbol_offset
);
818 ret
= mi_lttng_writer_write_element_string(writer
,
819 mi_lttng_element_kernel_probe_location_symbol_offset_name
,
826 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
827 mi_lttng_element_kernel_probe_location_symbol_offset_offset
,
833 /* Close kernel probe location symbol offset element. */
834 ret
= mi_lttng_writer_close_element(writer
);
843 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
849 enum lttng_error_code
lttng_kernel_probe_location_mi_serialize(
850 const struct lttng_kernel_probe_location
*location
,
851 struct mi_writer
*writer
)
854 enum lttng_error_code ret_code
;
856 LTTNG_ASSERT(location
);
857 LTTNG_ASSERT(writer
);
859 /* Open kernel probe location element. */
860 ret
= mi_lttng_writer_open_element(
861 writer
, mi_lttng_element_kernel_probe_location
);
866 /* Serialize the location sub type. */
867 ret_code
= location
->mi_serialize(location
, writer
);
868 if (ret_code
!= LTTNG_OK
) {
872 /* Close kernel probe location element. */
873 ret
= mi_lttng_writer_close_element(writer
);
882 ret_code
= LTTNG_ERR_MI_IO_FAIL
;