2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include "lttng/lttng-error.h"
10 #include <common/compat/string.h>
11 #include <common/error.h>
12 #include <common/macros.h>
13 #include <common/payload.h>
14 #include <common/payload-view.h>
15 #include <common/hashtable/hashtable.h>
16 #include <common/hashtable/utils.h>
18 #include <lttng/constant.h>
19 #include <lttng/userspace-probe-internal.h>
21 #include <sys/types.h>
22 #include <sys/unistd.h>
25 int lttng_userspace_probe_location_function_set_binary_fd_handle(
26 struct lttng_userspace_probe_location
*location
,
27 struct fd_handle
*binary_fd_handle
);
30 int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
31 struct lttng_userspace_probe_location
*location
,
32 struct fd_handle
*binary_fd_handle
);
34 enum lttng_userspace_probe_location_lookup_method_type
35 lttng_userspace_probe_location_lookup_method_get_type(
36 const struct lttng_userspace_probe_location_lookup_method
*lookup_method
)
38 return lookup_method
? lookup_method
->type
:
39 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_UNKNOWN
;
42 void lttng_userspace_probe_location_lookup_method_destroy(
43 struct lttng_userspace_probe_location_lookup_method
*lookup_method
)
52 struct lttng_userspace_probe_location_lookup_method
*
53 lttng_userspace_probe_location_lookup_method_function_elf_create(void)
55 struct lttng_userspace_probe_location_lookup_method
*ret
= NULL
;
56 struct lttng_userspace_probe_location_lookup_method_elf
*elf_method
;
58 elf_method
= zmalloc(sizeof(*elf_method
));
64 ret
= &elf_method
->parent
;
65 ret
->type
= LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
;
70 struct lttng_userspace_probe_location_lookup_method
*
71 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create(void)
73 struct lttng_userspace_probe_location_lookup_method
*ret
= NULL
;
74 struct lttng_userspace_probe_location_lookup_method_sdt
*sdt_method
;
76 sdt_method
= zmalloc(sizeof(*sdt_method
));
82 ret
= &sdt_method
->parent
;
83 ret
->type
= LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
;
88 enum lttng_userspace_probe_location_type
lttng_userspace_probe_location_get_type(
89 const struct lttng_userspace_probe_location
*location
)
91 return location
? location
->type
:
92 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN
;
96 void lttng_userspace_probe_location_function_destroy(
97 struct lttng_userspace_probe_location
*location
)
99 struct lttng_userspace_probe_location_function
*location_function
= NULL
;
103 location_function
= container_of(location
,
104 struct lttng_userspace_probe_location_function
, parent
);
106 assert(location_function
);
108 free(location_function
->function_name
);
109 free(location_function
->binary_path
);
110 fd_handle_put(location_function
->binary_fd_handle
);
115 void lttng_userspace_probe_location_tracepoint_destroy(
116 struct lttng_userspace_probe_location
*location
)
118 struct lttng_userspace_probe_location_tracepoint
*location_tracepoint
= NULL
;
122 location_tracepoint
= container_of(location
,
123 struct lttng_userspace_probe_location_tracepoint
,
126 assert(location_tracepoint
);
128 free(location_tracepoint
->probe_name
);
129 free(location_tracepoint
->provider_name
);
130 free(location_tracepoint
->binary_path
);
131 fd_handle_put(location_tracepoint
->binary_fd_handle
);
135 void lttng_userspace_probe_location_destroy(
136 struct lttng_userspace_probe_location
*location
)
142 lttng_userspace_probe_location_lookup_method_destroy(
143 location
->lookup_method
);
145 switch (location
->type
) {
146 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
147 lttng_userspace_probe_location_function_destroy(location
);
149 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
150 lttng_userspace_probe_location_tracepoint_destroy(location
);
157 /* Compare two file descriptors based on their inode and device numbers. */
158 static bool fd_is_equal(int a
, int b
)
161 bool is_equal
= false;
162 struct stat a_stat
, b_stat
;
164 if (a
< 0 && b
>= 0) {
168 if (b
< 0 && a
>= 0) {
172 if (a
< 0 && b
< 0) {
173 if (a
== -1 && b
== -1) {
178 /* Invalid state, abort. */
182 /* Both are valid file descriptors. */
183 ret
= fstat(a
, &a_stat
);
185 PERROR("Failed to fstat userspace probe location binary fd %d",
190 ret
= fstat(b
, &b_stat
);
192 PERROR("Failed to fstat userspace probe location binary fd %d",
197 is_equal
= (a_stat
.st_ino
== b_stat
.st_ino
) &&
198 (a_stat
.st_dev
== b_stat
.st_dev
);
204 static unsigned long lttng_userspace_probe_location_function_hash(
205 const struct lttng_userspace_probe_location
*location
)
207 unsigned long hash
= hash_key_ulong(
208 (void *) LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
,
210 struct lttng_userspace_probe_location_function
*function_location
=
211 container_of(location
, typeof(*function_location
),
214 hash
^= hash_key_str(function_location
->function_name
, lttng_ht_seed
);
215 hash
^= hash_key_str(function_location
->binary_path
, lttng_ht_seed
);
217 * No need to hash on the fd. Worst comes to worse,
218 * the equal function will discriminate.
223 static bool lttng_userspace_probe_location_function_is_equal(
224 const struct lttng_userspace_probe_location
*_a
,
225 const struct lttng_userspace_probe_location
*_b
)
227 bool is_equal
= false;
228 struct lttng_userspace_probe_location_function
*a
, *b
;
230 a
= container_of(_a
, struct lttng_userspace_probe_location_function
,
232 b
= container_of(_b
, struct lttng_userspace_probe_location_function
,
235 if (a
->instrumentation_type
!= b
->instrumentation_type
) {
239 assert(a
->function_name
);
240 assert(b
->function_name
);
241 if (strcmp(a
->function_name
, b
->function_name
)) {
245 assert(a
->binary_path
);
246 assert(b
->binary_path
);
247 if (strcmp(a
->binary_path
, b
->binary_path
)) {
251 is_equal
= fd_is_equal(a
->binary_fd_handle
? fd_handle_get_fd(a
->binary_fd_handle
) : -1,
252 b
->binary_fd_handle
? fd_handle_get_fd(b
->binary_fd_handle
) : -1);
257 static struct lttng_userspace_probe_location
*
258 lttng_userspace_probe_location_function_create_no_check(const char *binary_path
,
259 const char *function_name
,
260 struct lttng_userspace_probe_location_lookup_method
*lookup_method
,
264 struct fd_handle
*binary_fd_handle
= NULL
;
265 char *function_name_copy
= NULL
, *binary_path_copy
= NULL
;
266 struct lttng_userspace_probe_location
*ret
= NULL
;
267 struct lttng_userspace_probe_location_function
*location
;
270 binary_fd
= open(binary_path
, O_RDONLY
);
272 PERROR("Error opening the binary");
276 binary_fd_handle
= fd_handle_create(binary_fd
);
281 /* Ownership transferred to fd_handle. */
285 function_name_copy
= lttng_strndup(function_name
, LTTNG_SYMBOL_NAME_LEN
);
286 if (!function_name_copy
) {
287 PERROR("Error duplicating the function name");
291 binary_path_copy
= lttng_strndup(binary_path
, LTTNG_PATH_MAX
);
292 if (!binary_path_copy
) {
293 PERROR("Error duplicating the function name");
297 location
= zmalloc(sizeof(*location
));
299 PERROR("Error allocating userspace probe location");
303 location
->function_name
= function_name_copy
;
304 location
->binary_path
= binary_path_copy
;
305 location
->binary_fd_handle
= binary_fd_handle
;
306 binary_fd_handle
= NULL
;
307 location
->instrumentation_type
=
308 LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY
;
310 ret
= &location
->parent
;
311 ret
->lookup_method
= lookup_method
;
312 ret
->type
= LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
;
313 ret
->equal
= lttng_userspace_probe_location_function_is_equal
;
314 ret
->hash
= lttng_userspace_probe_location_function_hash
;
318 free(function_name_copy
);
319 free(binary_path_copy
);
320 if (binary_fd
>= 0) {
321 if (close(binary_fd
)) {
322 PERROR("Error closing binary fd in error path");
325 fd_handle_put(binary_fd_handle
);
330 static unsigned long lttng_userspace_probe_location_tracepoint_hash(
331 const struct lttng_userspace_probe_location
*location
)
333 unsigned long hash
= hash_key_ulong(
334 (void *) LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
,
336 struct lttng_userspace_probe_location_tracepoint
*tp_location
=
337 container_of(location
, typeof(*tp_location
), parent
);
339 hash
^= hash_key_str(tp_location
->probe_name
, lttng_ht_seed
);
340 hash
^= hash_key_str(tp_location
->provider_name
, lttng_ht_seed
);
341 hash
^= hash_key_str(tp_location
->binary_path
, lttng_ht_seed
);
343 * No need to hash on the fd. Worst comes to worse,
344 * the equal function will discriminate.
349 static bool lttng_userspace_probe_location_tracepoint_is_equal(
350 const struct lttng_userspace_probe_location
*_a
,
351 const struct lttng_userspace_probe_location
*_b
)
353 bool is_equal
= false;
354 struct lttng_userspace_probe_location_tracepoint
*a
, *b
;
356 a
= container_of(_a
, struct lttng_userspace_probe_location_tracepoint
,
358 b
= container_of(_b
, struct lttng_userspace_probe_location_tracepoint
,
361 assert(a
->probe_name
);
362 assert(b
->probe_name
);
363 if (strcmp(a
->probe_name
, b
->probe_name
)) {
367 assert(a
->provider_name
);
368 assert(b
->provider_name
);
369 if (strcmp(a
->provider_name
, b
->provider_name
)) {
373 assert(a
->binary_path
);
374 assert(b
->binary_path
);
375 if (strcmp(a
->binary_path
, b
->binary_path
)) {
379 is_equal
= fd_is_equal(a
->binary_fd_handle
? fd_handle_get_fd(a
->binary_fd_handle
) : -1,
380 b
->binary_fd_handle
? fd_handle_get_fd(b
->binary_fd_handle
) : -1);
386 static struct lttng_userspace_probe_location
*
387 lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_path
,
388 const char *provider_name
, const char *probe_name
,
389 struct lttng_userspace_probe_location_lookup_method
*lookup_method
,
393 struct fd_handle
*binary_fd_handle
= NULL
;
394 char *probe_name_copy
= NULL
;
395 char *provider_name_copy
= NULL
;
396 char *binary_path_copy
= NULL
;
397 struct lttng_userspace_probe_location
*ret
= NULL
;
398 struct lttng_userspace_probe_location_tracepoint
*location
;
401 binary_fd
= open(binary_path
, O_RDONLY
);
407 binary_fd_handle
= fd_handle_create(binary_fd
);
412 /* Ownership transferred to fd_handle. */
416 probe_name_copy
= lttng_strndup(probe_name
, LTTNG_SYMBOL_NAME_LEN
);
417 if (!probe_name_copy
) {
418 PERROR("lttng_strndup");
422 provider_name_copy
= lttng_strndup(provider_name
, LTTNG_SYMBOL_NAME_LEN
);
423 if (!provider_name_copy
) {
424 PERROR("lttng_strndup");
428 binary_path_copy
= lttng_strndup(binary_path
, LTTNG_PATH_MAX
);
429 if (!binary_path_copy
) {
430 PERROR("lttng_strndup");
434 location
= zmalloc(sizeof(*location
));
440 location
->probe_name
= probe_name_copy
;
441 location
->provider_name
= provider_name_copy
;
442 location
->binary_path
= binary_path_copy
;
443 location
->binary_fd_handle
= binary_fd_handle
;
444 binary_fd_handle
= NULL
;
446 ret
= &location
->parent
;
447 ret
->lookup_method
= lookup_method
;
448 ret
->type
= LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
;
449 ret
->equal
= lttng_userspace_probe_location_tracepoint_is_equal
;
450 ret
->hash
= lttng_userspace_probe_location_tracepoint_hash
;
454 free(probe_name_copy
);
455 free(provider_name_copy
);
456 free(binary_path_copy
);
457 if (binary_fd
>= 0) {
458 if (close(binary_fd
)) {
459 PERROR("Error closing binary fd in error path");
462 fd_handle_put(binary_fd_handle
);
467 struct lttng_userspace_probe_location
*
468 lttng_userspace_probe_location_function_create(const char *binary_path
,
469 const char *function_name
,
470 struct lttng_userspace_probe_location_lookup_method
*lookup_method
)
472 struct lttng_userspace_probe_location
*ret
= NULL
;
474 if (!binary_path
|| !function_name
) {
475 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
479 switch (lttng_userspace_probe_location_lookup_method_get_type(
481 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT
:
482 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
:
485 /* Invalid probe location lookup method. */
489 ret
= lttng_userspace_probe_location_function_create_no_check(
490 binary_path
, function_name
, lookup_method
, true);
495 struct lttng_userspace_probe_location
*
496 lttng_userspace_probe_location_tracepoint_create(const char *binary_path
,
497 const char *provider_name
, const char *probe_name
,
498 struct lttng_userspace_probe_location_lookup_method
*lookup_method
)
500 struct lttng_userspace_probe_location
*ret
= NULL
;
502 if (!binary_path
|| !probe_name
|| !provider_name
) {
503 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
507 switch (lttng_userspace_probe_location_lookup_method_get_type(
509 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
:
512 /* Invalid probe location lookup method. */
516 ret
= lttng_userspace_probe_location_tracepoint_create_no_check(
517 binary_path
, provider_name
, probe_name
, lookup_method
, true);
522 static struct lttng_userspace_probe_location_lookup_method
*
523 lttng_userspace_probe_location_lookup_method_function_elf_copy(
524 const struct lttng_userspace_probe_location_lookup_method
*lookup_method
)
526 struct lttng_userspace_probe_location_lookup_method
*parent
= NULL
;
527 struct lttng_userspace_probe_location_lookup_method_elf
*elf_method
;
529 assert(lookup_method
);
530 assert(lookup_method
->type
==
531 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
);
533 elf_method
= zmalloc(sizeof(*elf_method
));
535 PERROR("Error allocating ELF userspace probe lookup method");
539 elf_method
->parent
.type
= lookup_method
->type
;
540 parent
= &elf_method
->parent
;
549 static struct lttng_userspace_probe_location_lookup_method
*
550 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
551 struct lttng_userspace_probe_location_lookup_method
*lookup_method
)
553 struct lttng_userspace_probe_location_lookup_method
*parent
= NULL
;
554 struct lttng_userspace_probe_location_lookup_method_sdt
*sdt_method
;
556 assert(lookup_method
);
557 assert(lookup_method
->type
==
558 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
);
560 sdt_method
= zmalloc(sizeof(*sdt_method
));
566 sdt_method
->parent
.type
= lookup_method
->type
;
567 parent
= &sdt_method
->parent
;
577 static struct lttng_userspace_probe_location
*
578 lttng_userspace_probe_location_function_copy(
579 const struct lttng_userspace_probe_location
*location
)
581 enum lttng_userspace_probe_location_lookup_method_type lookup_type
;
582 struct lttng_userspace_probe_location
*new_location
= NULL
;
583 struct lttng_userspace_probe_location_lookup_method
*lookup_method
= NULL
;
584 const char *binary_path
= NULL
;
585 const char *function_name
= NULL
;
586 struct lttng_userspace_probe_location_function
*function_location
;
589 assert(location
->type
== LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
);
590 function_location
= container_of(
591 location
, typeof(*function_location
), parent
);
593 /* Get probe location fields */
594 binary_path
= lttng_userspace_probe_location_function_get_binary_path(location
);
596 ERR("Userspace probe binary path is NULL");
600 function_name
= lttng_userspace_probe_location_function_get_function_name(location
);
601 if (!function_name
) {
602 ERR("Userspace probe function name is NULL");
607 * Duplicate probe location method fields
609 lookup_type
= lttng_userspace_probe_location_lookup_method_get_type(
610 location
->lookup_method
);
611 switch (lookup_type
) {
612 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
:
614 lttng_userspace_probe_location_lookup_method_function_elf_copy(
615 location
->lookup_method
);
616 if (!lookup_method
) {
621 /* Invalid probe location lookup method. */
625 /* Create the probe_location */
626 new_location
= lttng_userspace_probe_location_function_create_no_check(
627 binary_path
, function_name
, lookup_method
, false);
629 goto destroy_lookup_method
;
632 /* Set the duplicated fd to the new probe_location */
633 if (lttng_userspace_probe_location_function_set_binary_fd_handle(new_location
,
634 function_location
->binary_fd_handle
) < 0) {
635 goto destroy_probe_location
;
640 destroy_probe_location
:
641 lttng_userspace_probe_location_destroy(new_location
);
642 destroy_lookup_method
:
643 lttng_userspace_probe_location_lookup_method_destroy(lookup_method
);
650 static struct lttng_userspace_probe_location
*
651 lttng_userspace_probe_location_tracepoint_copy(
652 const struct lttng_userspace_probe_location
*location
)
654 enum lttng_userspace_probe_location_lookup_method_type lookup_type
;
655 struct lttng_userspace_probe_location
*new_location
= NULL
;
656 struct lttng_userspace_probe_location_lookup_method
*lookup_method
= NULL
;
657 const char *binary_path
= NULL
;
658 const char *probe_name
= NULL
;
659 const char *provider_name
= NULL
;
660 struct lttng_userspace_probe_location_tracepoint
*tracepoint_location
;
663 assert(location
->type
== LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
);
664 tracepoint_location
= container_of(
665 location
, typeof(*tracepoint_location
), parent
);
667 /* Get probe location fields */
668 binary_path
= lttng_userspace_probe_location_tracepoint_get_binary_path(location
);
670 ERR("Userspace probe binary path is NULL");
674 probe_name
= lttng_userspace_probe_location_tracepoint_get_probe_name(location
);
676 ERR("Userspace probe probe name is NULL");
680 provider_name
= lttng_userspace_probe_location_tracepoint_get_provider_name(location
);
681 if (!provider_name
) {
682 ERR("Userspace probe provider name is NULL");
687 * Duplicate probe location method fields
689 lookup_type
= lttng_userspace_probe_location_lookup_method_get_type(
690 location
->lookup_method
);
691 switch (lookup_type
) {
692 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
:
694 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
695 location
->lookup_method
);
696 if (!lookup_method
) {
701 /* Invalid probe location lookup method. */
705 /* Create the probe_location */
706 new_location
= lttng_userspace_probe_location_tracepoint_create_no_check(
707 binary_path
, provider_name
, probe_name
, lookup_method
, false);
709 goto destroy_lookup_method
;
712 /* Set the duplicated fd to the new probe_location */
713 if (lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(new_location
,
714 tracepoint_location
->binary_fd_handle
) < 0) {
715 goto destroy_probe_location
;
720 destroy_probe_location
:
721 lttng_userspace_probe_location_destroy(new_location
);
722 destroy_lookup_method
:
723 lttng_userspace_probe_location_lookup_method_destroy(lookup_method
);
730 const char *lttng_userspace_probe_location_function_get_binary_path(
731 const struct lttng_userspace_probe_location
*location
)
733 const char *ret
= NULL
;
734 struct lttng_userspace_probe_location_function
*function_location
;
736 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
737 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
) {
738 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
742 function_location
= container_of(location
,
743 struct lttng_userspace_probe_location_function
,
745 ret
= function_location
->binary_path
;
750 const char *lttng_userspace_probe_location_tracepoint_get_binary_path(
751 const struct lttng_userspace_probe_location
*location
)
753 const char *ret
= NULL
;
754 struct lttng_userspace_probe_location_tracepoint
*tracepoint_location
;
756 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
757 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
) {
758 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
762 tracepoint_location
= container_of(location
,
763 struct lttng_userspace_probe_location_tracepoint
,
765 ret
= tracepoint_location
->binary_path
;
770 const char *lttng_userspace_probe_location_function_get_function_name(
771 const struct lttng_userspace_probe_location
*location
)
773 const char *ret
= NULL
;
774 struct lttng_userspace_probe_location_function
*function_location
;
776 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
777 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
) {
778 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
782 function_location
= container_of(location
,
783 struct lttng_userspace_probe_location_function
, parent
);
784 ret
= function_location
->function_name
;
789 const char *lttng_userspace_probe_location_tracepoint_get_probe_name(
790 const struct lttng_userspace_probe_location
*location
)
792 const char *ret
= NULL
;
793 struct lttng_userspace_probe_location_tracepoint
*tracepoint_location
;
795 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
796 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
) {
797 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
801 tracepoint_location
= container_of(location
,
802 struct lttng_userspace_probe_location_tracepoint
, parent
);
803 ret
= tracepoint_location
->probe_name
;
808 const char *lttng_userspace_probe_location_tracepoint_get_provider_name(
809 const struct lttng_userspace_probe_location
*location
)
811 const char *ret
= NULL
;
812 struct lttng_userspace_probe_location_tracepoint
*tracepoint_location
;
814 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
815 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
) {
816 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
820 tracepoint_location
= container_of(location
,
821 struct lttng_userspace_probe_location_tracepoint
, parent
);
822 ret
= tracepoint_location
->provider_name
;
827 int lttng_userspace_probe_location_function_get_binary_fd(
828 const struct lttng_userspace_probe_location
*location
)
831 struct lttng_userspace_probe_location_function
*function_location
;
833 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
834 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
) {
835 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
839 function_location
= container_of(location
,
840 struct lttng_userspace_probe_location_function
, parent
);
841 ret
= function_location
->binary_fd_handle
?
842 fd_handle_get_fd(function_location
->binary_fd_handle
) : -1;
847 enum lttng_userspace_probe_location_function_instrumentation_type
848 lttng_userspace_probe_location_function_get_instrumentation_type(
849 const struct lttng_userspace_probe_location
*location
)
851 enum lttng_userspace_probe_location_function_instrumentation_type type
;
852 struct lttng_userspace_probe_location_function
*function_location
;
854 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
855 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
) {
856 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
857 type
= LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_UNKNOWN
;
861 function_location
= container_of(location
,
862 struct lttng_userspace_probe_location_function
, parent
);
863 type
= function_location
->instrumentation_type
;
868 enum lttng_userspace_probe_location_status
869 lttng_userspace_probe_location_function_set_instrumentation_type(
870 const struct lttng_userspace_probe_location
*location
,
871 enum lttng_userspace_probe_location_function_instrumentation_type instrumentation_type
)
873 enum lttng_userspace_probe_location_status status
=
874 LTTNG_USERSPACE_PROBE_LOCATION_STATUS_OK
;
875 struct lttng_userspace_probe_location_function
*function_location
;
877 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
878 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
||
879 instrumentation_type
!=
880 LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY
) {
881 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
882 status
= LTTNG_USERSPACE_PROBE_LOCATION_STATUS_INVALID
;
886 function_location
= container_of(location
,
887 struct lttng_userspace_probe_location_function
, parent
);
888 function_location
->instrumentation_type
= instrumentation_type
;
893 int lttng_userspace_probe_location_tracepoint_get_binary_fd(
894 const struct lttng_userspace_probe_location
*location
)
897 struct lttng_userspace_probe_location_tracepoint
*tracepoint_location
;
899 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
900 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
) {
901 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
905 tracepoint_location
= container_of(location
,
906 struct lttng_userspace_probe_location_tracepoint
, parent
);
907 ret
= tracepoint_location
->binary_fd_handle
?
908 fd_handle_get_fd(tracepoint_location
->binary_fd_handle
) : -1;
913 static struct lttng_userspace_probe_location_lookup_method
*
914 lttng_userspace_probe_location_function_get_lookup_method(
915 const struct lttng_userspace_probe_location
*location
)
917 struct lttng_userspace_probe_location_lookup_method
*ret
= NULL
;
919 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
920 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
) {
921 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
925 ret
= location
->lookup_method
;
930 static struct lttng_userspace_probe_location_lookup_method
*
931 lttng_userspace_probe_location_tracepoint_get_lookup_method(
932 const struct lttng_userspace_probe_location
*location
)
934 struct lttng_userspace_probe_location_lookup_method
*ret
= NULL
;
936 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
937 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
) {
938 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
942 ret
= location
->lookup_method
;
947 const struct lttng_userspace_probe_location_lookup_method
*
948 lttng_userspace_probe_location_get_lookup_method(
949 const struct lttng_userspace_probe_location
*location
)
951 struct lttng_userspace_probe_location_lookup_method
*ret
= NULL
;
954 switch (location
->type
) {
955 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
956 ret
= lttng_userspace_probe_location_function_get_lookup_method(
959 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
960 ret
= lttng_userspace_probe_location_tracepoint_get_lookup_method(
964 ERR("Unknowned lookup method.");
971 int lttng_userspace_probe_location_lookup_method_serialize(
972 struct lttng_userspace_probe_location_lookup_method
*method
,
973 struct lttng_payload
*payload
)
976 struct lttng_userspace_probe_location_lookup_method_comm
979 lookup_method_comm
.type
= (int8_t) (method
? method
->type
:
980 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT
);
982 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &lookup_method_comm
,
983 sizeof(lookup_method_comm
));
988 ret
= sizeof(lookup_method_comm
);
994 int lttng_userspace_probe_location_function_serialize(
995 const struct lttng_userspace_probe_location
*location
,
996 struct lttng_payload
*payload
)
999 size_t function_name_len
, binary_path_len
;
1000 struct lttng_userspace_probe_location_function
*location_function
;
1001 struct lttng_userspace_probe_location_function_comm location_function_comm
;
1004 assert(lttng_userspace_probe_location_get_type(location
) ==
1005 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
);
1007 location_function
= container_of(location
,
1008 struct lttng_userspace_probe_location_function
,
1010 if (!location_function
->function_name
|| !location_function
->binary_path
) {
1011 ret
= -LTTNG_ERR_INVALID
;
1015 if (payload
&& !location_function
->binary_fd_handle
) {
1016 ret
= -LTTNG_ERR_INVALID
;
1020 function_name_len
= strlen(location_function
->function_name
);
1021 if (function_name_len
== 0) {
1022 ret
= -LTTNG_ERR_INVALID
;
1025 binary_path_len
= strlen(location_function
->binary_path
);
1026 if (binary_path_len
== 0) {
1027 ret
= -LTTNG_ERR_INVALID
;
1031 location_function_comm
.function_name_len
= function_name_len
+ 1;
1032 location_function_comm
.binary_path_len
= binary_path_len
+ 1;
1035 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
1036 &location_function_comm
,
1037 sizeof(location_function_comm
));
1039 ret
= -LTTNG_ERR_INVALID
;
1042 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
1043 location_function
->function_name
,
1044 location_function_comm
.function_name_len
);
1046 ret
= -LTTNG_ERR_INVALID
;
1049 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
1050 location_function
->binary_path
,
1051 location_function_comm
.binary_path_len
);
1053 ret
= -LTTNG_ERR_INVALID
;
1056 ret
= lttng_payload_push_fd_handle(
1057 payload
, location_function
->binary_fd_handle
);
1059 ret
= -LTTNG_ERR_INVALID
;
1063 ret
= sizeof(location_function_comm
) +
1064 location_function_comm
.function_name_len
+
1065 location_function_comm
.binary_path_len
;
1071 int lttng_userspace_probe_location_tracepoint_serialize(
1072 const struct lttng_userspace_probe_location
*location
,
1073 struct lttng_payload
*payload
)
1076 size_t probe_name_len
, provider_name_len
, binary_path_len
;
1077 struct lttng_userspace_probe_location_tracepoint
*location_tracepoint
;
1078 struct lttng_userspace_probe_location_tracepoint_comm location_tracepoint_comm
;
1081 assert(lttng_userspace_probe_location_get_type(location
) ==
1082 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
);
1084 location_tracepoint
= container_of(location
,
1085 struct lttng_userspace_probe_location_tracepoint
,
1087 if (!location_tracepoint
->probe_name
||
1088 !location_tracepoint
->provider_name
||
1089 !location_tracepoint
->binary_path
) {
1090 ret
= -LTTNG_ERR_INVALID
;
1094 if (payload
&& !location_tracepoint
->binary_fd_handle
) {
1095 ret
= -LTTNG_ERR_INVALID
;
1099 probe_name_len
= strlen(location_tracepoint
->probe_name
);
1100 if (probe_name_len
== 0) {
1101 ret
= -LTTNG_ERR_INVALID
;
1105 provider_name_len
= strlen(location_tracepoint
->provider_name
);
1106 if (provider_name_len
== 0) {
1107 ret
= -LTTNG_ERR_INVALID
;
1111 binary_path_len
= strlen(location_tracepoint
->binary_path
);
1112 if (binary_path_len
== 0) {
1113 ret
= -LTTNG_ERR_INVALID
;
1117 location_tracepoint_comm
.probe_name_len
= probe_name_len
+ 1;
1118 location_tracepoint_comm
.provider_name_len
= provider_name_len
+ 1;
1119 location_tracepoint_comm
.binary_path_len
= binary_path_len
+ 1;
1122 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
1123 &location_tracepoint_comm
,
1124 sizeof(location_tracepoint_comm
));
1126 ret
= -LTTNG_ERR_INVALID
;
1129 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
1130 location_tracepoint
->probe_name
,
1131 location_tracepoint_comm
.probe_name_len
);
1133 ret
= -LTTNG_ERR_INVALID
;
1136 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
1137 location_tracepoint
->provider_name
,
1138 location_tracepoint_comm
.provider_name_len
);
1140 ret
= -LTTNG_ERR_INVALID
;
1143 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
1144 location_tracepoint
->binary_path
,
1145 location_tracepoint_comm
.binary_path_len
);
1147 ret
= -LTTNG_ERR_INVALID
;
1150 ret
= lttng_payload_push_fd_handle(
1151 payload
, location_tracepoint
->binary_fd_handle
);
1153 ret
= -LTTNG_ERR_INVALID
;
1158 ret
= sizeof(location_tracepoint_comm
) +
1159 location_tracepoint_comm
.probe_name_len
+
1160 location_tracepoint_comm
.provider_name_len
+
1161 location_tracepoint_comm
.binary_path_len
;
1167 int lttng_userspace_probe_location_serialize(
1168 const struct lttng_userspace_probe_location
*location
,
1169 struct lttng_payload
*payload
)
1171 int ret
, buffer_use
= 0;
1172 struct lttng_userspace_probe_location_comm location_generic_comm
;
1175 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__
);
1176 ret
= -LTTNG_ERR_INVALID
;
1180 memset(&location_generic_comm
, 0, sizeof(location_generic_comm
));
1182 location_generic_comm
.type
= (int8_t) location
->type
;
1184 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
1185 &location_generic_comm
,
1186 sizeof(location_generic_comm
));
1191 buffer_use
+= sizeof(location_generic_comm
);
1193 switch (lttng_userspace_probe_location_get_type(location
)) {
1194 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
1195 ret
= lttng_userspace_probe_location_function_serialize(
1198 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
1199 ret
= lttng_userspace_probe_location_tracepoint_serialize(
1203 ERR("Unsupported probe location type");
1204 ret
= -LTTNG_ERR_INVALID
;
1212 ret
= lttng_userspace_probe_location_lookup_method_serialize(
1213 location
->lookup_method
, payload
);
1223 int lttng_userspace_probe_location_function_create_from_payload(
1224 struct lttng_payload_view
*view
,
1225 struct lttng_userspace_probe_location
**location
)
1227 struct lttng_userspace_probe_location_function_comm
*location_function_comm
;
1228 const char *function_name_src
, *binary_path_src
;
1229 char *function_name
= NULL
, *binary_path
= NULL
;
1231 size_t expected_size
;
1232 struct fd_handle
*binary_fd_handle
= lttng_payload_view_pop_fd_handle(view
);
1236 if (view
->buffer
.size
< sizeof(*location_function_comm
)) {
1237 ret
= -LTTNG_ERR_INVALID
;
1241 location_function_comm
=
1242 (typeof(location_function_comm
)) view
->buffer
.data
;
1244 expected_size
= sizeof(*location_function_comm
) +
1245 location_function_comm
->function_name_len
+
1246 location_function_comm
->binary_path_len
;
1248 if (view
->buffer
.size
< expected_size
) {
1249 ret
= -LTTNG_ERR_INVALID
;
1253 function_name_src
= view
->buffer
.data
+ sizeof(*location_function_comm
);
1254 binary_path_src
= function_name_src
+
1255 location_function_comm
->function_name_len
;
1257 if (!lttng_buffer_view_contains_string(&view
->buffer
, function_name_src
,
1258 location_function_comm
->function_name_len
)) {
1259 ret
= -LTTNG_ERR_INVALID
;
1263 if (!lttng_buffer_view_contains_string(&view
->buffer
, binary_path_src
,
1264 location_function_comm
->binary_path_len
)) {
1265 ret
= -LTTNG_ERR_INVALID
;
1269 function_name
= lttng_strndup(function_name_src
, LTTNG_SYMBOL_NAME_LEN
);
1270 if (!function_name
) {
1271 PERROR("lttng_strndup");
1272 ret
= -LTTNG_ERR_NOMEM
;
1276 binary_path
= lttng_strndup(binary_path_src
, LTTNG_PATH_MAX
);
1278 PERROR("lttng_strndup");
1279 ret
= -LTTNG_ERR_NOMEM
;
1283 *location
= lttng_userspace_probe_location_function_create_no_check(
1284 binary_path
, function_name
, NULL
, false);
1286 ret
= -LTTNG_ERR_INVALID
;
1290 ret
= lttng_userspace_probe_location_function_set_binary_fd_handle(
1291 *location
, binary_fd_handle
);
1293 ret
= -LTTNG_ERR_INVALID
;
1297 ret
= (int) expected_size
;
1299 fd_handle_put(binary_fd_handle
);
1300 free(function_name
);
1306 int lttng_userspace_probe_location_tracepoint_create_from_payload(
1307 struct lttng_payload_view
*view
,
1308 struct lttng_userspace_probe_location
**location
)
1310 struct lttng_userspace_probe_location_tracepoint_comm
*location_tracepoint_comm
;
1311 const char *probe_name_src
, *provider_name_src
, *binary_path_src
;
1312 char *probe_name
= NULL
, *provider_name
= NULL
, *binary_path
= NULL
;
1314 size_t expected_size
;
1315 struct fd_handle
*binary_fd_handle
= lttng_payload_view_pop_fd_handle(view
);
1319 if (!binary_fd_handle
) {
1320 ret
= -LTTNG_ERR_INVALID
;
1324 if (view
->buffer
.size
< sizeof(*location_tracepoint_comm
)) {
1325 ret
= -LTTNG_ERR_INVALID
;
1329 location_tracepoint_comm
=
1330 (typeof(location_tracepoint_comm
)) view
->buffer
.data
;
1332 expected_size
= sizeof(*location_tracepoint_comm
) +
1333 location_tracepoint_comm
->probe_name_len
+
1334 location_tracepoint_comm
->provider_name_len
+
1335 location_tracepoint_comm
->binary_path_len
;
1337 if (view
->buffer
.size
< expected_size
) {
1338 ret
= -LTTNG_ERR_INVALID
;
1342 probe_name_src
= view
->buffer
.data
+ sizeof(*location_tracepoint_comm
);
1343 provider_name_src
= probe_name_src
+
1344 location_tracepoint_comm
->probe_name_len
;
1345 binary_path_src
= provider_name_src
+
1346 location_tracepoint_comm
->provider_name_len
;
1348 if (!lttng_buffer_view_contains_string(&view
->buffer
, probe_name_src
,
1349 location_tracepoint_comm
->probe_name_len
)) {
1350 ret
= -LTTNG_ERR_INVALID
;
1354 if (!lttng_buffer_view_contains_string(&view
->buffer
, provider_name_src
,
1355 location_tracepoint_comm
->provider_name_len
)) {
1356 ret
= -LTTNG_ERR_INVALID
;
1360 if (!lttng_buffer_view_contains_string(&view
->buffer
, binary_path_src
,
1361 location_tracepoint_comm
->binary_path_len
)) {
1362 ret
= -LTTNG_ERR_INVALID
;
1366 probe_name
= lttng_strndup(probe_name_src
, LTTNG_SYMBOL_NAME_LEN
);
1368 PERROR("lttng_strndup");
1371 provider_name
= lttng_strndup(provider_name_src
, LTTNG_SYMBOL_NAME_LEN
);
1372 if (!provider_name
) {
1373 PERROR("lttng_strndup");
1377 binary_path
= lttng_strndup(binary_path_src
, LTTNG_SYMBOL_NAME_LEN
);
1379 PERROR("lttng_strndup");
1383 *location
= lttng_userspace_probe_location_tracepoint_create_no_check(
1384 binary_path
, provider_name
, probe_name
, NULL
, false);
1386 ret
= -LTTNG_ERR_INVALID
;
1390 ret
= lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
1391 *location
, binary_fd_handle
);
1393 ret
= -LTTNG_ERR_INVALID
;
1397 ret
= (int) expected_size
;
1399 fd_handle_put(binary_fd_handle
);
1401 free(provider_name
);
1407 int lttng_userspace_probe_location_lookup_method_create_from_payload(
1408 struct lttng_payload_view
*view
,
1409 struct lttng_userspace_probe_location_lookup_method
**lookup_method
)
1412 struct lttng_userspace_probe_location_lookup_method_comm
*lookup_comm
;
1413 enum lttng_userspace_probe_location_lookup_method_type type
;
1416 assert(lookup_method
);
1418 if (view
->buffer
.size
< sizeof(*lookup_comm
)) {
1419 ret
= -LTTNG_ERR_INVALID
;
1423 lookup_comm
= (typeof(lookup_comm
)) view
->buffer
.data
;
1424 type
= (enum lttng_userspace_probe_location_lookup_method_type
)
1427 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT
:
1428 *lookup_method
= NULL
;
1430 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
:
1432 lttng_userspace_probe_location_lookup_method_function_elf_create();
1433 if (!(*lookup_method
)) {
1434 ret
= -LTTNG_ERR_INVALID
;
1438 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
:
1440 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1441 if (!(*lookup_method
)) {
1442 ret
= -LTTNG_ERR_INVALID
;
1447 ret
= -LTTNG_ERR_INVALID
;
1451 ret
= sizeof(*lookup_comm
);
1457 int lttng_userspace_probe_location_create_from_payload(
1458 struct lttng_payload_view
*view
,
1459 struct lttng_userspace_probe_location
**location
)
1461 struct lttng_userspace_probe_location_lookup_method
*lookup_method
;
1462 enum lttng_userspace_probe_location_type type
;
1465 struct lttng_userspace_probe_location_comm
*probe_location_comm
;
1466 struct lttng_payload_view probe_location_comm_view
=
1467 lttng_payload_view_from_view(
1468 view
, 0, sizeof(*probe_location_comm
));
1473 lookup_method
= NULL
;
1475 if (!lttng_payload_view_is_valid(&probe_location_comm_view
)) {
1476 ret
= -LTTNG_ERR_INVALID
;
1480 probe_location_comm
= (typeof(probe_location_comm
)) probe_location_comm_view
.buffer
.data
;
1481 type
= (enum lttng_userspace_probe_location_type
) probe_location_comm
->type
;
1482 consumed
+= sizeof(*probe_location_comm
);
1485 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
1487 struct lttng_payload_view location_view
=
1488 lttng_payload_view_from_view(
1489 view
, consumed
, -1);
1491 ret
= lttng_userspace_probe_location_function_create_from_payload(
1492 &location_view
, location
);
1498 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
1500 struct lttng_payload_view location_view
=
1501 lttng_payload_view_from_view(view
, consumed
, -1);
1503 ret
= lttng_userspace_probe_location_tracepoint_create_from_payload(
1504 &location_view
, location
);
1511 ret
= -LTTNG_ERR_INVALID
;
1516 if (view
->buffer
.size
<= consumed
) {
1517 ret
= -LTTNG_ERR_INVALID
;
1522 struct lttng_payload_view lookup_method_view
=
1523 lttng_payload_view_from_view(
1524 view
, consumed
, -1);
1526 ret
= lttng_userspace_probe_location_lookup_method_create_from_payload(
1527 &lookup_method_view
, &lookup_method
);
1530 ret
= -LTTNG_ERR_INVALID
;
1534 assert(lookup_method
);
1535 (*location
)->lookup_method
= lookup_method
;
1536 lookup_method
= NULL
;
1543 int lttng_userspace_probe_location_function_set_binary_fd_handle(
1544 struct lttng_userspace_probe_location
*location
,
1545 struct fd_handle
*binary_fd
)
1548 struct lttng_userspace_probe_location_function
*function_location
;
1551 assert(location
->type
== LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
);
1553 function_location
= container_of(location
,
1554 struct lttng_userspace_probe_location_function
, parent
);
1555 fd_handle_put(function_location
->binary_fd_handle
);
1556 fd_handle_get(binary_fd
);
1557 function_location
->binary_fd_handle
= binary_fd
;
1562 int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
1563 struct lttng_userspace_probe_location
*location
,
1564 struct fd_handle
*binary_fd
)
1567 struct lttng_userspace_probe_location_tracepoint
*tracepoint_location
;
1570 assert(location
->type
== LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
);
1572 tracepoint_location
= container_of(location
,
1573 struct lttng_userspace_probe_location_tracepoint
, parent
);
1574 fd_handle_put(tracepoint_location
->binary_fd_handle
);
1575 fd_handle_get(binary_fd
);
1576 tracepoint_location
->binary_fd_handle
= binary_fd
;
1581 int lttng_userspace_probe_location_function_flatten(
1582 const struct lttng_userspace_probe_location
*location
,
1583 struct lttng_dynamic_buffer
*buffer
)
1585 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method
;
1586 struct lttng_userspace_probe_location_function
*probe_function
;
1587 struct lttng_userspace_probe_location_function flat_probe
;
1588 size_t function_name_len
, binary_path_len
;
1589 size_t padding_needed
= 0;
1590 char *flat_probe_start
;
1591 int storage_needed
= 0;
1596 if (location
->lookup_method
&& location
->lookup_method
->type
!=
1597 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
) {
1598 ret
= -LTTNG_ERR_INVALID
;
1602 probe_function
= container_of(location
,
1603 struct lttng_userspace_probe_location_function
,
1605 assert(probe_function
->function_name
);
1606 assert(probe_function
->binary_path
);
1609 sizeof(struct lttng_userspace_probe_location_function
);
1610 function_name_len
= strlen(probe_function
->function_name
) + 1;
1611 binary_path_len
= strlen(probe_function
->binary_path
) + 1;
1612 storage_needed
+= function_name_len
+ binary_path_len
;
1615 * The lookup method is aligned to 64-bit within the buffer.
1616 * This is needed even if there is no lookup method since
1617 * the next structure in the buffer probably needs to be
1618 * aligned too (depending on the arch).
1620 padding_needed
= ALIGN_TO(storage_needed
, sizeof(uint64_t)) - storage_needed
;
1621 storage_needed
+= padding_needed
;
1623 if (location
->lookup_method
) {
1624 /* NOTE: elf look-up method is assumed here. */
1625 storage_needed
+= sizeof(struct lttng_userspace_probe_location_lookup_method_elf
);
1629 ret
= storage_needed
;
1633 if (lttng_dynamic_buffer_get_capacity_left(buffer
) < storage_needed
) {
1634 ret
= lttng_dynamic_buffer_set_capacity(buffer
,
1635 buffer
->size
+ storage_needed
);
1641 memset(&flat_probe
, 0, sizeof(flat_probe
));
1643 flat_probe_start
= buffer
->data
+ buffer
->size
;
1644 flat_probe
.parent
.type
= location
->type
;
1646 * The lookup method, if present, is the last element in the flat
1647 * representation of the probe.
1649 if (location
->lookup_method
) {
1650 flat_probe
.parent
.lookup_method
=
1651 (struct lttng_userspace_probe_location_lookup_method
*)
1652 (flat_probe_start
+ sizeof(flat_probe
) +
1653 function_name_len
+ binary_path_len
+ padding_needed
);
1655 flat_probe
.parent
.lookup_method
= NULL
;
1658 flat_probe
.function_name
= flat_probe_start
+ sizeof(flat_probe
);
1659 flat_probe
.binary_path
= flat_probe
.function_name
+ function_name_len
;
1660 flat_probe
.binary_fd_handle
= NULL
;
1661 ret
= lttng_dynamic_buffer_append(buffer
, &flat_probe
,
1662 sizeof(flat_probe
));
1667 ret
= lttng_dynamic_buffer_append(buffer
,
1668 probe_function
->function_name
, function_name_len
);
1672 ret
= lttng_dynamic_buffer_append(buffer
,
1673 probe_function
->binary_path
, binary_path_len
);
1678 /* Insert padding before the lookup method. */
1679 ret
= lttng_dynamic_buffer_set_size(buffer
,
1680 buffer
->size
+ padding_needed
);
1685 if (!location
->lookup_method
) {
1686 /* Not an error, the default method is used. */
1687 ret
= storage_needed
;
1691 memset(&flat_lookup_method
, 0, sizeof(flat_lookup_method
));
1692 flat_lookup_method
.parent
.type
=
1693 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
;
1694 ret
= lttng_dynamic_buffer_append(buffer
,
1695 &flat_lookup_method
, sizeof(flat_lookup_method
));
1699 ret
= storage_needed
;
1705 int lttng_userspace_probe_location_tracepoint_flatten(
1706 const struct lttng_userspace_probe_location
*location
,
1707 struct lttng_dynamic_buffer
*buffer
)
1709 struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method
;
1710 struct lttng_userspace_probe_location_tracepoint
*probe_tracepoint
;
1711 struct lttng_userspace_probe_location_tracepoint flat_probe
;
1712 size_t probe_name_len
, provider_name_len
, binary_path_len
;
1713 size_t padding_needed
= 0;
1714 int storage_needed
= 0;
1715 char *flat_probe_start
;
1720 /* Only SDT tracepoints are supported at the moment */
1721 if (location
->lookup_method
&& location
->lookup_method
->type
!=
1722 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
) {
1723 ret
= -LTTNG_ERR_INVALID
;
1726 probe_tracepoint
= container_of(location
,
1727 struct lttng_userspace_probe_location_tracepoint
,
1729 assert(probe_tracepoint
->probe_name
);
1730 assert(probe_tracepoint
->provider_name
);
1731 assert(probe_tracepoint
->binary_path
);
1733 /* Compute the storage space needed to flatten the probe location */
1734 storage_needed
+= sizeof(struct lttng_userspace_probe_location_tracepoint
);
1736 probe_name_len
= strlen(probe_tracepoint
->probe_name
) + 1;
1737 provider_name_len
= strlen(probe_tracepoint
->provider_name
) + 1;
1738 binary_path_len
= strlen(probe_tracepoint
->binary_path
) + 1;
1740 storage_needed
+= probe_name_len
+ provider_name_len
+ binary_path_len
;
1743 * The lookup method is aligned to 64-bit within the buffer.
1744 * This is needed even if there is no lookup method since
1745 * the next structure in the buffer probably needs to be
1746 * aligned too (depending on the arch).
1748 padding_needed
= ALIGN_TO(storage_needed
, sizeof(uint64_t)) - storage_needed
;
1749 storage_needed
+= padding_needed
;
1751 if (location
->lookup_method
) {
1752 /* NOTE: elf look-up method is assumed here. */
1754 sizeof(struct lttng_userspace_probe_location_lookup_method_elf
);
1758 * If the caller set buffer to NULL, return the size of the needed buffer.
1761 ret
= storage_needed
;
1765 if (lttng_dynamic_buffer_get_capacity_left(buffer
) < storage_needed
) {
1766 ret
= lttng_dynamic_buffer_set_capacity(buffer
,
1767 buffer
->size
+ storage_needed
);
1773 memset(&flat_probe
, 0, sizeof(flat_probe
));
1775 flat_probe_start
= buffer
->data
+ buffer
->size
;
1776 flat_probe
.parent
.type
= location
->type
;
1779 * The lookup method, if present, is the last element in the flat
1780 * representation of the probe.
1782 if (location
->lookup_method
) {
1783 flat_probe
.parent
.lookup_method
=
1784 (struct lttng_userspace_probe_location_lookup_method
*)
1785 (flat_probe_start
+ sizeof(flat_probe
) +
1786 probe_name_len
+ provider_name_len
+
1787 binary_path_len
+ padding_needed
);
1789 flat_probe
.parent
.lookup_method
= NULL
;
1792 flat_probe
.probe_name
= flat_probe_start
+ sizeof(flat_probe
);
1793 flat_probe
.provider_name
= flat_probe
.probe_name
+ probe_name_len
;
1794 flat_probe
.binary_path
= flat_probe
.provider_name
+ provider_name_len
;
1795 flat_probe
.binary_fd_handle
= NULL
;
1796 ret
= lttng_dynamic_buffer_append(buffer
, &flat_probe
, sizeof(flat_probe
));
1801 /* Append all the fields to the buffer */
1802 ret
= lttng_dynamic_buffer_append(buffer
,
1803 probe_tracepoint
->probe_name
, probe_name_len
);
1807 ret
= lttng_dynamic_buffer_append(buffer
,
1808 probe_tracepoint
->provider_name
, provider_name_len
);
1812 ret
= lttng_dynamic_buffer_append(buffer
,
1813 probe_tracepoint
->binary_path
, binary_path_len
);
1818 /* Insert padding before the lookup method. */
1819 ret
= lttng_dynamic_buffer_set_size(buffer
, buffer
->size
+ padding_needed
);
1824 if (!location
->lookup_method
) {
1825 /* Not an error, the default method is used. */
1826 ret
= storage_needed
;
1830 memset(&flat_lookup_method
, 0, sizeof(flat_lookup_method
));
1832 flat_lookup_method
.parent
.type
=
1833 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
;
1834 ret
= lttng_dynamic_buffer_append(buffer
,
1835 &flat_lookup_method
, sizeof(flat_lookup_method
));
1839 ret
= storage_needed
;
1845 int lttng_userspace_probe_location_flatten(
1846 const struct lttng_userspace_probe_location
*location
,
1847 struct lttng_dynamic_buffer
*buffer
)
1851 ret
= -LTTNG_ERR_INVALID
;
1855 /* Only types currently supported. */
1856 switch (location
->type
) {
1857 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
1858 ret
= lttng_userspace_probe_location_function_flatten(location
, buffer
);
1860 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
1861 ret
= lttng_userspace_probe_location_tracepoint_flatten(location
, buffer
);
1864 ret
= -LTTNG_ERR_INVALID
;
1873 struct lttng_userspace_probe_location
*lttng_userspace_probe_location_copy(
1874 const struct lttng_userspace_probe_location
*location
)
1876 struct lttng_userspace_probe_location
*new_location
= NULL
;
1877 enum lttng_userspace_probe_location_type type
;
1883 type
= lttng_userspace_probe_location_get_type(location
);
1885 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
1887 lttng_userspace_probe_location_function_copy(location
);
1888 if (!new_location
) {
1892 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
1894 lttng_userspace_probe_location_tracepoint_copy(location
);
1895 if (!new_location
) {
1900 new_location
= NULL
;
1904 return new_location
;
1908 bool lttng_userspace_probe_location_lookup_method_is_equal(
1909 const struct lttng_userspace_probe_location_lookup_method
*a
,
1910 const struct lttng_userspace_probe_location_lookup_method
*b
)
1912 bool is_equal
= false;
1923 if (a
->type
!= b
->type
) {
1933 bool lttng_userspace_probe_location_is_equal(
1934 const struct lttng_userspace_probe_location
*a
,
1935 const struct lttng_userspace_probe_location
*b
)
1937 bool is_equal
= false;
1948 if (!lttng_userspace_probe_location_lookup_method_is_equal(
1949 a
->lookup_method
, b
->lookup_method
)) {
1953 if (a
->type
!= b
->type
) {
1957 is_equal
= a
->equal
? a
->equal(a
, b
) : true;
1963 unsigned long lttng_userspace_probe_location_hash(
1964 const struct lttng_userspace_probe_location
*location
)
1966 return location
->hash(location
);