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/hashtable/hashtable.h>
12 #include <common/hashtable/utils.h>
13 #include <common/macros.h>
14 #include <common/mi-lttng.h>
15 #include <common/payload-view.h>
16 #include <common/payload.h>
18 #include <lttng/constant.h>
19 #include <lttng/kernel-probe-internal.h>
20 #include <lttng/kernel-probe.h>
22 #include <sys/types.h>
23 #include <sys/unistd.h>
26 int lttng_kernel_probe_location_address_serialize(
27 const struct lttng_kernel_probe_location
*location
,
28 struct lttng_payload
*payload
);
31 int lttng_kernel_probe_location_symbol_serialize(
32 const struct lttng_kernel_probe_location
*location
,
33 struct lttng_payload
*payload
);
36 bool lttng_kernel_probe_location_address_is_equal(
37 const struct lttng_kernel_probe_location
*a
,
38 const struct lttng_kernel_probe_location
*b
);
41 bool lttng_kernel_probe_location_symbol_is_equal(
42 const struct lttng_kernel_probe_location
*a
,
43 const struct lttng_kernel_probe_location
*b
);
46 unsigned long lttng_kernel_probe_location_address_hash(
47 const struct lttng_kernel_probe_location
*location
);
50 unsigned long lttng_kernel_probe_location_symbol_hash(
51 const struct lttng_kernel_probe_location
*location
);
54 enum lttng_error_code
lttng_kernel_probe_location_address_mi_serialize(
55 const struct lttng_kernel_probe_location
*location
,
56 struct mi_writer
*writer
);
59 enum lttng_error_code
lttng_kernel_probe_location_symbol_mi_serialize(
60 const struct lttng_kernel_probe_location
*location
,
61 struct mi_writer
*writer
);
63 enum lttng_kernel_probe_location_type
lttng_kernel_probe_location_get_type(
64 const struct lttng_kernel_probe_location
*location
)
66 return location
? location
->type
:
67 LTTNG_KERNEL_PROBE_LOCATION_TYPE_UNKNOWN
;
71 void lttng_kernel_probe_location_address_destroy(
72 struct lttng_kernel_probe_location
*location
)
79 void lttng_kernel_probe_location_symbol_destroy(
80 struct lttng_kernel_probe_location
*location
)
82 struct lttng_kernel_probe_location_symbol
*location_symbol
= NULL
;
86 location_symbol
= container_of(location
,
87 struct lttng_kernel_probe_location_symbol
,
90 assert(location_symbol
);
92 free(location_symbol
->symbol_name
);
96 void lttng_kernel_probe_location_destroy(
97 struct lttng_kernel_probe_location
*location
)
103 switch (location
->type
) {
104 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
105 lttng_kernel_probe_location_address_destroy(location
);
107 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
108 lttng_kernel_probe_location_symbol_destroy(location
);
115 struct lttng_kernel_probe_location
*
116 lttng_kernel_probe_location_address_create(uint64_t address
)
118 struct lttng_kernel_probe_location
*ret
= NULL
;
119 struct lttng_kernel_probe_location_address
*location
;
121 location
= zmalloc(sizeof(*location
));
123 PERROR("Error allocating userspace probe location.");
127 location
->address
= address
;
129 ret
= &location
->parent
;
130 ret
->type
= LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
;
131 ret
->equal
= lttng_kernel_probe_location_address_is_equal
;
132 ret
->serialize
= lttng_kernel_probe_location_address_serialize
;
133 ret
->hash
= lttng_kernel_probe_location_address_hash
;
134 ret
->mi_serialize
= lttng_kernel_probe_location_address_mi_serialize
;
140 struct lttng_kernel_probe_location
*
141 lttng_kernel_probe_location_symbol_create(const char *symbol_name
,
144 char *symbol_name_copy
= NULL
;
145 struct lttng_kernel_probe_location
*ret
= NULL
;
146 struct lttng_kernel_probe_location_symbol
*location
;
148 if (!symbol_name
|| strlen(symbol_name
) >= LTTNG_SYMBOL_NAME_LEN
) {
152 symbol_name_copy
= strdup(symbol_name
);
153 if (!symbol_name_copy
) {
154 PERROR("Failed to copy symbol name '%s'", symbol_name
);
158 location
= zmalloc(sizeof(*location
));
160 PERROR("Failed to allocate kernel symbol probe location");
164 location
->symbol_name
= symbol_name_copy
;
165 location
->offset
= offset
;
167 ret
= &location
->parent
;
168 ret
->type
= LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
;
169 ret
->equal
= lttng_kernel_probe_location_symbol_is_equal
;
170 ret
->serialize
= lttng_kernel_probe_location_symbol_serialize
;
171 ret
->hash
= lttng_kernel_probe_location_symbol_hash
;
172 ret
->mi_serialize
= lttng_kernel_probe_location_symbol_mi_serialize
;
176 free(symbol_name_copy
);
181 enum lttng_kernel_probe_location_status
182 lttng_kernel_probe_location_address_get_address(
183 const struct lttng_kernel_probe_location
*location
,
186 enum lttng_kernel_probe_location_status ret
=
187 LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
;
188 struct lttng_kernel_probe_location_address
*address_location
;
192 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
193 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
) {
194 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
195 ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID
;
199 address_location
= container_of(location
,
200 struct lttng_kernel_probe_location_address
, parent
);
201 *offset
= address_location
->address
;
206 const char *lttng_kernel_probe_location_symbol_get_name(
207 const struct lttng_kernel_probe_location
*location
)
209 const char *ret
= NULL
;
210 struct lttng_kernel_probe_location_symbol
*symbol_location
;
212 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
213 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
) {
214 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
218 symbol_location
= container_of(location
,
219 struct lttng_kernel_probe_location_symbol
, parent
);
220 ret
= symbol_location
->symbol_name
;
225 enum lttng_kernel_probe_location_status
226 lttng_kernel_probe_location_symbol_get_offset(
227 const struct lttng_kernel_probe_location
*location
,
230 enum lttng_kernel_probe_location_status ret
=
231 LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
;
232 struct lttng_kernel_probe_location_symbol
*symbol_location
;
236 if (!location
|| lttng_kernel_probe_location_get_type(location
) !=
237 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
) {
238 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
239 ret
= LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID
;
243 symbol_location
= container_of(location
,
244 struct lttng_kernel_probe_location_symbol
, parent
);
245 *offset
= symbol_location
->offset
;
251 int lttng_kernel_probe_location_symbol_serialize(
252 const struct lttng_kernel_probe_location
*location
,
253 struct lttng_payload
*payload
)
256 size_t symbol_name_len
;
257 size_t original_payload_size
;
258 struct lttng_kernel_probe_location_symbol
*location_symbol
;
259 struct lttng_kernel_probe_location_symbol_comm location_symbol_comm
;
261 if (!location
|| !payload
) {
262 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
263 ret
= -LTTNG_ERR_INVALID
;
267 assert(lttng_kernel_probe_location_get_type(location
) ==
268 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
270 original_payload_size
= payload
->buffer
.size
;
271 location_symbol
= container_of(location
,
272 struct lttng_kernel_probe_location_symbol
, parent
);
274 if (!location_symbol
->symbol_name
) {
275 ret
= -LTTNG_ERR_INVALID
;
279 symbol_name_len
= strlen(location_symbol
->symbol_name
);
280 if (symbol_name_len
== 0) {
281 ret
= -LTTNG_ERR_INVALID
;
285 location_symbol_comm
.symbol_len
= symbol_name_len
+ 1;
286 location_symbol_comm
.offset
= location_symbol
->offset
;
288 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
289 &location_symbol_comm
, sizeof(location_symbol_comm
));
291 ret
= -LTTNG_ERR_INVALID
;
295 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
296 location_symbol
->symbol_name
,
297 location_symbol_comm
.symbol_len
);
299 ret
= -LTTNG_ERR_INVALID
;
303 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
309 int lttng_kernel_probe_location_address_serialize(
310 const struct lttng_kernel_probe_location
*location
,
311 struct lttng_payload
*payload
)
314 size_t original_payload_size
;
315 struct lttng_kernel_probe_location_address
*location_address
;
316 struct lttng_kernel_probe_location_address_comm location_address_comm
;
319 assert(lttng_kernel_probe_location_get_type(location
) ==
320 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
322 original_payload_size
= payload
->buffer
.size
;
323 location_address
= container_of(location
,
324 struct lttng_kernel_probe_location_address
,
327 location_address_comm
.address
= location_address
->address
;
329 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
330 &location_address_comm
,
331 sizeof(location_address_comm
));
333 ret
= -LTTNG_ERR_INVALID
;
337 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
343 int lttng_kernel_probe_location_serialize(
344 const struct lttng_kernel_probe_location
*location
,
345 struct lttng_payload
*payload
)
348 size_t original_payload_size
;
349 struct lttng_kernel_probe_location_comm location_generic_comm
= {};
351 if (!location
|| !payload
) {
352 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
353 ret
= -LTTNG_ERR_INVALID
;
357 original_payload_size
= payload
->buffer
.size
;
358 location_generic_comm
.type
= (int8_t) location
->type
;
359 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
360 &location_generic_comm
,
361 sizeof(location_generic_comm
));
366 ret
= location
->serialize(location
, payload
);
371 ret
= (int) (payload
->buffer
.size
- original_payload_size
);
377 int lttng_kernel_probe_location_symbol_create_from_payload(
378 struct lttng_payload_view
*view
,
379 struct lttng_kernel_probe_location
**location
)
381 struct lttng_kernel_probe_location_symbol_comm
*location_symbol_comm
;
382 const char *symbol_name_src
;
384 size_t expected_size
;
388 if (view
->buffer
.size
< sizeof(*location_symbol_comm
)) {
389 ret
= -LTTNG_ERR_INVALID
;
393 location_symbol_comm
=
394 (typeof(location_symbol_comm
)) view
->buffer
.data
;
396 expected_size
= sizeof(*location_symbol_comm
) +
397 location_symbol_comm
->symbol_len
;
399 if (view
->buffer
.size
< expected_size
) {
400 ret
= -LTTNG_ERR_INVALID
;
404 symbol_name_src
= view
->buffer
.data
+ sizeof(*location_symbol_comm
);
406 if (!lttng_buffer_view_contains_string(&view
->buffer
, symbol_name_src
,
407 location_symbol_comm
->symbol_len
)) {
408 ret
= -LTTNG_ERR_INVALID
;
412 *location
= lttng_kernel_probe_location_symbol_create(
413 symbol_name_src
, location_symbol_comm
->offset
);
415 ret
= -LTTNG_ERR_INVALID
;
419 ret
= (ssize_t
) expected_size
;
425 ssize_t
lttng_kernel_probe_location_address_create_from_payload(
426 struct lttng_payload_view
*view
,
427 struct lttng_kernel_probe_location
**location
)
429 struct lttng_kernel_probe_location_address_comm
*location_address_comm
;
431 size_t expected_size
;
435 expected_size
= sizeof(*location_address_comm
);
437 if (view
->buffer
.size
< expected_size
) {
438 ret
= -LTTNG_ERR_INVALID
;
442 location_address_comm
=
443 (typeof(location_address_comm
)) view
->buffer
.data
;
445 *location
= lttng_kernel_probe_location_address_create(location_address_comm
->address
);
447 ret
= -LTTNG_ERR_INVALID
;
451 ret
= (size_t) expected_size
;
457 ssize_t
lttng_kernel_probe_location_create_from_payload(
458 struct lttng_payload_view
*view
,
459 struct lttng_kernel_probe_location
**location
)
461 enum lttng_kernel_probe_location_type type
;
462 ssize_t consumed
= 0;
464 const struct lttng_kernel_probe_location_comm
*probe_location_comm
;
465 const struct lttng_payload_view probe_location_comm_view
=
466 lttng_payload_view_from_view(
467 view
, 0, sizeof(*probe_location_comm
));
472 if (!lttng_payload_view_is_valid(&probe_location_comm_view
)) {
473 ret
= -LTTNG_ERR_INVALID
;
477 probe_location_comm
= (typeof(probe_location_comm
)) probe_location_comm_view
.buffer
.data
;
478 type
= (enum lttng_kernel_probe_location_type
) probe_location_comm
->type
;
479 consumed
+= sizeof(*probe_location_comm
);
482 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
484 struct lttng_payload_view location_view
=
485 lttng_payload_view_from_view(
488 ret
= lttng_kernel_probe_location_symbol_create_from_payload(
489 &location_view
, location
);
492 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
494 struct lttng_payload_view location_view
=
495 lttng_payload_view_from_view(view
, consumed
, -1);
497 ret
= lttng_kernel_probe_location_address_create_from_payload(
498 &location_view
, location
);
502 ret
= -LTTNG_ERR_INVALID
;
507 ret
= -LTTNG_ERR_INVALID
;
518 unsigned long lttng_kernel_probe_location_address_hash(
519 const struct lttng_kernel_probe_location
*location
)
521 unsigned long hash
= hash_key_ulong(
522 (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
,
524 struct lttng_kernel_probe_location_address
*address_location
=
525 container_of(location
, typeof(*address_location
),
528 hash
^= hash_key_u64(&address_location
->address
, lttng_ht_seed
);
534 bool lttng_kernel_probe_location_address_is_equal(
535 const struct lttng_kernel_probe_location
*_a
,
536 const struct lttng_kernel_probe_location
*_b
)
538 bool is_equal
= false;
539 struct lttng_kernel_probe_location_address
*a
, *b
;
541 a
= container_of(_a
, struct lttng_kernel_probe_location_address
,
543 b
= container_of(_b
, struct lttng_kernel_probe_location_address
,
546 if (a
->address
!= b
->address
) {
557 unsigned long lttng_kernel_probe_location_symbol_hash(
558 const struct lttng_kernel_probe_location
*location
)
560 unsigned long hash
= hash_key_ulong(
561 (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
,
563 struct lttng_kernel_probe_location_symbol
*symbol_location
=
564 container_of(location
, typeof(*symbol_location
),
567 hash
^= hash_key_str(symbol_location
->symbol_name
, lttng_ht_seed
);
568 hash
^= hash_key_u64(&symbol_location
->offset
, lttng_ht_seed
);
574 bool lttng_kernel_probe_location_symbol_is_equal(
575 const struct lttng_kernel_probe_location
*_a
,
576 const struct lttng_kernel_probe_location
*_b
)
578 bool is_equal
= false;
579 struct lttng_kernel_probe_location_symbol
*a
, *b
;
581 a
= container_of(_a
, struct lttng_kernel_probe_location_symbol
,
583 b
= container_of(_b
, struct lttng_kernel_probe_location_symbol
,
586 assert(a
->symbol_name
);
587 assert(b
->symbol_name
);
588 if (strcmp(a
->symbol_name
, b
->symbol_name
)) {
592 if (a
->offset
!= b
->offset
) {
603 bool lttng_kernel_probe_location_is_equal(
604 const struct lttng_kernel_probe_location
*a
,
605 const struct lttng_kernel_probe_location
*b
)
607 bool is_equal
= false;
618 if (a
->type
!= b
->type
) {
622 is_equal
= a
->equal
? a
->equal(a
, b
) : true;
627 static struct lttng_kernel_probe_location
*
628 lttng_kernel_probe_location_symbol_copy(
629 const struct lttng_kernel_probe_location
*location
)
631 struct lttng_kernel_probe_location
*new_location
= NULL
;
632 struct lttng_kernel_probe_location_symbol
*symbol_location
;
633 enum lttng_kernel_probe_location_status status
;
634 const char *symbol_name
= NULL
;
638 assert(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
639 symbol_location
= container_of(
640 location
, typeof(*symbol_location
), parent
);
642 /* Get probe location offset */
643 status
= lttng_kernel_probe_location_symbol_get_offset(location
, &offset
);
644 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
645 ERR("Get kernel probe location offset failed.");
649 symbol_name
= lttng_kernel_probe_location_symbol_get_name(location
);
651 ERR("Kernel probe symbol name is NULL.");
655 /* Create the probe_location */
656 new_location
= lttng_kernel_probe_location_symbol_create(
657 symbol_name
, offset
);
666 static struct lttng_kernel_probe_location
*
667 lttng_kernel_probe_location_address_copy(
668 const struct lttng_kernel_probe_location
*location
)
670 struct lttng_kernel_probe_location
*new_location
= NULL
;
671 struct lttng_kernel_probe_location_address
*address_location
;
672 enum lttng_kernel_probe_location_status status
;
676 assert(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
677 address_location
= container_of(
678 location
, typeof(*address_location
), parent
);
681 /* Get probe location fields */
682 status
= lttng_kernel_probe_location_address_get_address(location
, &address
);
683 if (status
!= LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
) {
684 ERR("Get kernel probe address failed.");
688 /* Create the probe_location */
689 new_location
= lttng_kernel_probe_location_address_create(address
);
700 struct lttng_kernel_probe_location
*lttng_kernel_probe_location_copy(
701 const struct lttng_kernel_probe_location
*location
)
703 struct lttng_kernel_probe_location
*new_location
= NULL
;
704 enum lttng_kernel_probe_location_type type
;
710 type
= lttng_kernel_probe_location_get_type(location
);
712 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
:
714 lttng_kernel_probe_location_address_copy(location
);
719 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
:
721 lttng_kernel_probe_location_symbol_copy(location
);
735 unsigned long lttng_kernel_probe_location_hash(
736 const struct lttng_kernel_probe_location
*location
)
738 return location
->hash(location
);
742 enum lttng_error_code
lttng_kernel_probe_location_address_mi_serialize(
743 const struct lttng_kernel_probe_location
*location
,
744 struct mi_writer
*writer
)
747 enum lttng_error_code ret_code
;
748 enum lttng_kernel_probe_location_status status
;
753 assert(location
->type
== LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS
);
755 status
= lttng_kernel_probe_location_address_get_address(
757 assert(status
== LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
);
759 /* Open kernel probe location address element. */
760 ret
= mi_lttng_writer_open_element(
761 writer
, mi_lttng_element_kernel_probe_location_address
);
766 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
767 mi_lttng_element_kernel_probe_location_address_address
,
773 /* Close kernel probe location address element. */
774 ret
= mi_lttng_writer_close_element(writer
);
783 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
789 enum lttng_error_code
lttng_kernel_probe_location_symbol_mi_serialize(
790 const struct lttng_kernel_probe_location
*location
,
791 struct mi_writer
*writer
)
794 enum lttng_error_code ret_code
;
795 enum lttng_kernel_probe_location_status status
;
796 const char *name
= NULL
;
801 assert(location
->type
==
802 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET
);
804 name
= lttng_kernel_probe_location_symbol_get_name(location
);
807 status
= lttng_kernel_probe_location_symbol_get_offset(
809 assert(status
== LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK
);
811 /* Open kernel probe location symbol offset element. */
812 ret
= mi_lttng_writer_open_element(writer
,
813 mi_lttng_element_kernel_probe_location_symbol_offset
);
819 ret
= mi_lttng_writer_write_element_string(writer
,
820 mi_lttng_element_kernel_probe_location_symbol_offset_name
,
827 ret
= mi_lttng_writer_write_element_unsigned_int(writer
,
828 mi_lttng_element_kernel_probe_location_symbol_offset_offset
,
834 /* Close kernel probe location symbol offset element. */
835 ret
= mi_lttng_writer_close_element(writer
);
844 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
850 enum lttng_error_code
lttng_kernel_probe_location_mi_serialize(
851 const struct lttng_kernel_probe_location
*location
,
852 struct mi_writer
*writer
)
855 enum lttng_error_code ret_code
;
860 /* Open kernel probe location element. */
861 ret
= mi_lttng_writer_open_element(
862 writer
, mi_lttng_element_kernel_probe_location
);
867 /* Serialize the location sub type. */
868 ret_code
= location
->mi_serialize(location
, writer
);
869 if (ret_code
!= LTTNG_OK
) {
873 /* Close kernel probe location element. */
874 ret
= mi_lttng_writer_close_element(writer
);
883 ret_code
= LTTNG_ERR_MI_IO_FAIL
;