2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <common/error.h>
20 #include <common/macros.h>
21 #include <common/compat/string.h>
23 #include <lttng/constant.h>
24 #include <lttng/userspace-probe-internal.h>
26 enum lttng_userspace_probe_location_lookup_method_type
27 lttng_userspace_probe_location_lookup_method_get_type(
28 const struct lttng_userspace_probe_location_lookup_method
*lookup_method
)
30 return lookup_method
? lookup_method
->type
:
31 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_UNKNOWN
;
34 void lttng_userspace_probe_location_lookup_method_destroy(
35 struct lttng_userspace_probe_location_lookup_method
*lookup_method
)
44 struct lttng_userspace_probe_location_lookup_method
*
45 lttng_userspace_probe_location_lookup_method_function_elf_create(void)
47 struct lttng_userspace_probe_location_lookup_method
*ret
= NULL
;
48 struct lttng_userspace_probe_location_lookup_method_elf
*elf_method
;
50 elf_method
= zmalloc(sizeof(*elf_method
));
56 ret
= &elf_method
->parent
;
57 ret
->type
= LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
;
62 struct lttng_userspace_probe_location_lookup_method
*
63 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create(void)
65 struct lttng_userspace_probe_location_lookup_method
*ret
= NULL
;
66 struct lttng_userspace_probe_location_lookup_method_sdt
*sdt_method
;
68 sdt_method
= zmalloc(sizeof(*sdt_method
));
74 ret
= &sdt_method
->parent
;
75 ret
->type
= LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
;
80 enum lttng_userspace_probe_location_type
lttng_userspace_probe_location_get_type(
81 const struct lttng_userspace_probe_location
*location
)
83 return location
? location
->type
:
84 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN
;
88 void lttng_userspace_probe_location_function_destroy(
89 struct lttng_userspace_probe_location
*location
)
91 struct lttng_userspace_probe_location_function
*location_function
= NULL
;
95 location_function
= container_of(location
,
96 struct lttng_userspace_probe_location_function
, parent
);
98 assert(location_function
);
100 free(location_function
->function_name
);
101 free(location_function
->binary_path
);
102 if (location_function
->binary_fd
>= 0) {
103 if (close(location_function
->binary_fd
)) {
111 void lttng_userspace_probe_location_tracepoint_destroy(
112 struct lttng_userspace_probe_location
*location
)
114 struct lttng_userspace_probe_location_tracepoint
*location_tracepoint
= NULL
;
118 location_tracepoint
= container_of(location
,
119 struct lttng_userspace_probe_location_tracepoint
,
122 assert(location_tracepoint
);
124 free(location_tracepoint
->probe_name
);
125 free(location_tracepoint
->provider_name
);
126 free(location_tracepoint
->binary_path
);
127 if (location_tracepoint
->binary_fd
>= 0) {
128 if (close(location_tracepoint
->binary_fd
)) {
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 static struct lttng_userspace_probe_location
*
158 lttng_userspace_probe_location_function_create_no_check(const char *binary_path
,
159 const char *function_name
,
160 struct lttng_userspace_probe_location_lookup_method
*lookup_method
,
164 char *function_name_copy
= NULL
, *binary_path_copy
= NULL
;
165 struct lttng_userspace_probe_location
*ret
= NULL
;
166 struct lttng_userspace_probe_location_function
*location
;
169 binary_fd
= open(binary_path
, O_RDONLY
);
171 PERROR("Error opening the binary");
178 function_name_copy
= lttng_strndup(function_name
, LTTNG_SYMBOL_NAME_LEN
);
179 if (!function_name_copy
) {
180 PERROR("Error duplicating the function name");
184 binary_path_copy
= lttng_strndup(binary_path
, LTTNG_PATH_MAX
);
185 if (!binary_path_copy
) {
186 PERROR("Error duplicating the function name");
190 location
= zmalloc(sizeof(*location
));
192 PERROR("Error allocating userspace probe location");
196 location
->function_name
= function_name_copy
;
197 location
->binary_path
= binary_path_copy
;
198 location
->binary_fd
= binary_fd
;
200 ret
= &location
->parent
;
201 ret
->lookup_method
= lookup_method
;
202 ret
->type
= LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
;
206 free(function_name_copy
);
207 free(binary_path_copy
);
208 if (binary_fd
>= 0) {
209 if (close(binary_fd
)) {
210 PERROR("Error closing binary fd in error path");
217 static struct lttng_userspace_probe_location
*
218 lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_path
,
219 const char *provider_name
, const char *probe_name
,
220 struct lttng_userspace_probe_location_lookup_method
*lookup_method
,
224 char *probe_name_copy
= NULL
;
225 char *provider_name_copy
= NULL
;
226 char *binary_path_copy
= NULL
;
227 struct lttng_userspace_probe_location
*ret
= NULL
;
228 struct lttng_userspace_probe_location_tracepoint
*location
;
231 binary_fd
= open(binary_path
, O_RDONLY
);
240 probe_name_copy
= lttng_strndup(probe_name
, LTTNG_SYMBOL_NAME_LEN
);
241 if (!probe_name_copy
) {
242 PERROR("lttng_strndup");
246 provider_name_copy
= lttng_strndup(provider_name
, LTTNG_SYMBOL_NAME_LEN
);
247 if (!provider_name_copy
) {
248 PERROR("lttng_strndup");
252 binary_path_copy
= lttng_strndup(binary_path
, LTTNG_PATH_MAX
);
253 if (!binary_path_copy
) {
254 PERROR("lttng_strndup");
258 location
= zmalloc(sizeof(*location
));
264 location
->probe_name
= probe_name_copy
;
265 location
->provider_name
= provider_name_copy
;
266 location
->binary_path
= binary_path_copy
;
267 location
->binary_fd
= binary_fd
;
269 ret
= &location
->parent
;
270 ret
->lookup_method
= lookup_method
;
271 ret
->type
= LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
;
275 free(probe_name_copy
);
276 free(provider_name_copy
);
277 if (binary_fd
>= 0) {
278 if (close(binary_fd
)) {
279 PERROR("Error closing binary fd in error path");
286 struct lttng_userspace_probe_location
*
287 lttng_userspace_probe_location_function_create(const char *binary_path
,
288 const char *function_name
,
289 struct lttng_userspace_probe_location_lookup_method
*lookup_method
)
291 struct lttng_userspace_probe_location
*ret
= NULL
;
293 if (!binary_path
|| !function_name
) {
294 ERR("Invalid argument(s)");
298 switch (lttng_userspace_probe_location_lookup_method_get_type(
300 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT
:
301 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
:
304 /* Invalid probe location lookup method. */
308 ret
= lttng_userspace_probe_location_function_create_no_check(
309 binary_path
, function_name
, lookup_method
, true);
314 struct lttng_userspace_probe_location
*
315 lttng_userspace_probe_location_tracepoint_create(const char *binary_path
,
316 const char *provider_name
, const char *probe_name
,
317 struct lttng_userspace_probe_location_lookup_method
*lookup_method
)
319 struct lttng_userspace_probe_location
*ret
= NULL
;
321 if (!binary_path
|| !probe_name
|| !provider_name
) {
322 ERR("Invalid argument(s)");
326 switch (lttng_userspace_probe_location_lookup_method_get_type(
328 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
:
331 /* Invalid probe location lookup method. */
335 ret
= lttng_userspace_probe_location_tracepoint_create_no_check(
336 binary_path
, provider_name
, probe_name
, lookup_method
, true);
341 static struct lttng_userspace_probe_location_lookup_method
*
342 lttng_userspace_probe_location_lookup_method_function_elf_copy(
343 const struct lttng_userspace_probe_location_lookup_method
*lookup_method
)
345 struct lttng_userspace_probe_location_lookup_method
*parent
= NULL
;
346 struct lttng_userspace_probe_location_lookup_method_elf
*elf_method
;
348 assert(lookup_method
);
349 assert(lookup_method
->type
==
350 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
);
352 elf_method
= zmalloc(sizeof(*elf_method
));
354 PERROR("Error allocating ELF userspace probe lookup method");
358 elf_method
->parent
.type
= lookup_method
->type
;
359 parent
= &elf_method
->parent
;
368 static struct lttng_userspace_probe_location_lookup_method
*
369 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
370 struct lttng_userspace_probe_location_lookup_method
*lookup_method
)
372 struct lttng_userspace_probe_location_lookup_method
*parent
= NULL
;
373 struct lttng_userspace_probe_location_lookup_method_sdt
*sdt_method
;
375 assert(lookup_method
);
376 assert(lookup_method
->type
==
377 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
);
379 sdt_method
= zmalloc(sizeof(*sdt_method
));
385 sdt_method
->parent
.type
= lookup_method
->type
;
386 parent
= &sdt_method
->parent
;
396 static struct lttng_userspace_probe_location
*
397 lttng_userspace_probe_location_function_copy(
398 const struct lttng_userspace_probe_location
*location
)
400 enum lttng_userspace_probe_location_lookup_method_type lookup_type
;
401 struct lttng_userspace_probe_location
*new_location
= NULL
;
402 struct lttng_userspace_probe_location_lookup_method
*lookup_method
= NULL
;
403 char *binary_path
= NULL
;
404 char *function_name
= NULL
;
408 assert(location
->type
== LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
);
410 /* Duplicate probe location fields */
412 lttng_strndup(lttng_userspace_probe_location_function_get_binary_path(location
),
419 lttng_strndup(lttng_userspace_probe_location_function_get_function_name(location
),
420 LTTNG_SYMBOL_NAME_LEN
);
421 if (!function_name
) {
422 PERROR("Error duplicating function name string");
426 /* Duplicate the binary fd */
427 fd
= dup(lttng_userspace_probe_location_function_get_binary_fd(location
));
429 PERROR("Error duplicating file descriptor to binary");
434 * Duplicate probe location method fields
436 lookup_type
= lttng_userspace_probe_location_lookup_method_get_type(
437 location
->lookup_method
);
438 switch (lookup_type
) {
439 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
:
441 lttng_userspace_probe_location_lookup_method_function_elf_copy(
442 location
->lookup_method
);
443 if (!lookup_method
) {
448 /* Invalid probe location lookup method. */
452 /* Create the probe_location */
453 new_location
= lttng_userspace_probe_location_function_create_no_check(
454 binary_path
, function_name
, lookup_method
, true);
456 goto destroy_lookup_method
;
459 /* Set the duplicated fd to the new probe_location */
460 if (lttng_userspace_probe_location_function_set_binary_fd(new_location
, fd
) < 0) {
461 goto destroy_probe_location
;
466 destroy_probe_location
:
467 lttng_userspace_probe_location_destroy(new_location
);
468 destroy_lookup_method
:
469 lttng_userspace_probe_location_lookup_method_destroy(lookup_method
);
472 PERROR("Error closing duplicated file descriptor in error path");
482 static struct lttng_userspace_probe_location
*
483 lttng_userspace_probe_location_tracepoint_copy(
484 const struct lttng_userspace_probe_location
*location
)
486 enum lttng_userspace_probe_location_lookup_method_type lookup_type
;
487 struct lttng_userspace_probe_location
*new_location
= NULL
;
488 struct lttng_userspace_probe_location_lookup_method
*lookup_method
= NULL
;
489 char *binary_path
= NULL
;
490 char *probe_name
= NULL
;
491 char *provider_name
= NULL
;
495 assert(location
->type
== LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
);
497 /* Duplicate probe location fields */
499 lttng_strndup(lttng_userspace_probe_location_tracepoint_get_binary_path(location
),
502 PERROR("lttng_strndup");
507 lttng_strndup(lttng_userspace_probe_location_tracepoint_get_probe_name(location
),
508 LTTNG_SYMBOL_NAME_LEN
);
510 PERROR("lttng_strndup");
515 lttng_strndup(lttng_userspace_probe_location_tracepoint_get_provider_name(location
),
516 LTTNG_SYMBOL_NAME_LEN
);
517 if (!provider_name
) {
518 PERROR("lttng_strndup");
522 /* Duplicate the binary fd */
523 fd
= dup(lttng_userspace_probe_location_tracepoint_get_binary_fd(location
));
530 * Duplicate probe location method fields
532 lookup_type
= lttng_userspace_probe_location_lookup_method_get_type(
533 location
->lookup_method
);
534 switch (lookup_type
) {
535 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
:
537 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
538 location
->lookup_method
);
539 if (!lookup_method
) {
544 /* Invalid probe location lookup method. */
548 /* Create the probe_location */
549 new_location
= lttng_userspace_probe_location_tracepoint_create_no_check(
550 binary_path
, provider_name
, probe_name
, lookup_method
, true);
552 goto destroy_lookup_method
;
555 /* Set the duplicated fd to the new probe_location */
556 if (lttng_userspace_probe_location_tracepoint_set_binary_fd(new_location
, fd
) < 0) {
557 goto destroy_probe_location
;
562 destroy_probe_location
:
563 lttng_userspace_probe_location_destroy(new_location
);
564 destroy_lookup_method
:
565 lttng_userspace_probe_location_lookup_method_destroy(lookup_method
);
579 const char *lttng_userspace_probe_location_function_get_binary_path(
580 const struct lttng_userspace_probe_location
*location
)
582 const char *ret
= NULL
;
583 struct lttng_userspace_probe_location_function
*function_location
;
585 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
586 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
) {
587 ERR("Invalid argument(s)");
591 function_location
= container_of(location
,
592 struct lttng_userspace_probe_location_function
,
594 ret
= function_location
->binary_path
;
599 const char *lttng_userspace_probe_location_tracepoint_get_binary_path(
600 const struct lttng_userspace_probe_location
*location
)
602 const char *ret
= NULL
;
603 struct lttng_userspace_probe_location_tracepoint
*tracepoint_location
;
605 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
606 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
) {
607 ERR("Invalid argument(s)");
611 tracepoint_location
= container_of(location
,
612 struct lttng_userspace_probe_location_tracepoint
,
614 ret
= tracepoint_location
->binary_path
;
619 const char *lttng_userspace_probe_location_function_get_function_name(
620 const struct lttng_userspace_probe_location
*location
)
622 const char *ret
= NULL
;
623 struct lttng_userspace_probe_location_function
*function_location
;
625 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
626 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
) {
627 ERR("Invalid argument(s)");
631 function_location
= container_of(location
,
632 struct lttng_userspace_probe_location_function
, parent
);
633 ret
= function_location
->function_name
;
638 const char *lttng_userspace_probe_location_tracepoint_get_probe_name(
639 const struct lttng_userspace_probe_location
*location
)
641 const char *ret
= NULL
;
642 struct lttng_userspace_probe_location_tracepoint
*tracepoint_location
;
644 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
645 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
) {
646 ERR("Invalid argument(s)");
650 tracepoint_location
= container_of(location
,
651 struct lttng_userspace_probe_location_tracepoint
, parent
);
652 ret
= tracepoint_location
->probe_name
;
657 const char *lttng_userspace_probe_location_tracepoint_get_provider_name(
658 const struct lttng_userspace_probe_location
*location
)
660 const char *ret
= NULL
;
661 struct lttng_userspace_probe_location_tracepoint
*tracepoint_location
;
663 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
664 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
) {
665 ERR("Invalid argument(s)");
669 tracepoint_location
= container_of(location
,
670 struct lttng_userspace_probe_location_tracepoint
, parent
);
671 ret
= tracepoint_location
->provider_name
;
676 int lttng_userspace_probe_location_function_get_binary_fd(
677 const struct lttng_userspace_probe_location
*location
)
680 struct lttng_userspace_probe_location_function
*function_location
;
682 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
683 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
) {
684 ERR("Invalid argument(s)");
688 function_location
= container_of(location
,
689 struct lttng_userspace_probe_location_function
, parent
);
690 ret
= function_location
->binary_fd
;
695 int lttng_userspace_probe_location_tracepoint_get_binary_fd(
696 const struct lttng_userspace_probe_location
*location
)
699 struct lttng_userspace_probe_location_tracepoint
*tracepoint_location
;
701 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
702 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
) {
703 ERR("Invalid argument(s)");
707 tracepoint_location
= container_of(location
,
708 struct lttng_userspace_probe_location_tracepoint
, parent
);
709 ret
= tracepoint_location
->binary_fd
;
714 static struct lttng_userspace_probe_location_lookup_method
*
715 lttng_userspace_probe_location_function_get_lookup_method(
716 const struct lttng_userspace_probe_location
*location
)
718 struct lttng_userspace_probe_location_lookup_method
*ret
= NULL
;
720 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
721 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
) {
722 ERR("Invalid argument(s)");
726 ret
= location
->lookup_method
;
731 static struct lttng_userspace_probe_location_lookup_method
*
732 lttng_userspace_probe_location_tracepoint_get_lookup_method(
733 const struct lttng_userspace_probe_location
*location
)
735 struct lttng_userspace_probe_location_lookup_method
*ret
= NULL
;
737 if (!location
|| lttng_userspace_probe_location_get_type(location
) !=
738 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
) {
739 ERR("Invalid argument(s)");
743 ret
= location
->lookup_method
;
748 const struct lttng_userspace_probe_location_lookup_method
*
749 lttng_userspace_probe_location_get_lookup_method(
750 const struct lttng_userspace_probe_location
*location
)
752 struct lttng_userspace_probe_location_lookup_method
*ret
= NULL
;
755 switch (location
->type
) {
756 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
757 ret
= lttng_userspace_probe_location_function_get_lookup_method(
760 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
761 ret
= lttng_userspace_probe_location_tracepoint_get_lookup_method(
765 ERR("Unknowned lookup method.");
772 int lttng_userspace_probe_location_lookup_method_serialize(
773 struct lttng_userspace_probe_location_lookup_method
*method
,
774 struct lttng_dynamic_buffer
*buffer
)
777 struct lttng_userspace_probe_location_lookup_method_comm
780 lookup_method_comm
.type
= (int8_t) (method
? method
->type
:
781 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT
);
783 ret
= lttng_dynamic_buffer_append(buffer
, &lookup_method_comm
,
784 sizeof(lookup_method_comm
));
789 ret
= sizeof(lookup_method_comm
);
795 int lttng_userspace_probe_location_function_serialize(
796 const struct lttng_userspace_probe_location
*location
,
797 struct lttng_dynamic_buffer
*buffer
,
801 size_t function_name_len
, binary_path_len
;
802 struct lttng_userspace_probe_location_function
*location_function
;
803 struct lttng_userspace_probe_location_function_comm location_function_comm
;
806 assert(lttng_userspace_probe_location_get_type(location
) ==
807 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
);
809 location_function
= container_of(location
,
810 struct lttng_userspace_probe_location_function
,
812 if (!location_function
->function_name
|| !location_function
->binary_path
) {
813 ret
= -LTTNG_ERR_INVALID
;
817 if (binary_fd
&& location_function
->binary_fd
< 0) {
818 ret
= -LTTNG_ERR_INVALID
;
823 *binary_fd
= location_function
->binary_fd
;
826 function_name_len
= strlen(location_function
->function_name
);
827 if (function_name_len
== 0) {
828 ret
= -LTTNG_ERR_INVALID
;
831 binary_path_len
= strlen(location_function
->binary_path
);
832 if (binary_path_len
== 0) {
833 ret
= -LTTNG_ERR_INVALID
;
837 location_function_comm
.function_name_len
= function_name_len
+ 1;
838 location_function_comm
.binary_path_len
= binary_path_len
+ 1;
841 ret
= lttng_dynamic_buffer_append(buffer
,
842 &location_function_comm
,
843 sizeof(location_function_comm
));
845 ret
= -LTTNG_ERR_INVALID
;
848 ret
= lttng_dynamic_buffer_append(buffer
,
849 location_function
->function_name
,
850 location_function_comm
.function_name_len
);
852 ret
= -LTTNG_ERR_INVALID
;
855 ret
= lttng_dynamic_buffer_append(buffer
,
856 location_function
->binary_path
,
857 location_function_comm
.binary_path_len
);
859 ret
= -LTTNG_ERR_INVALID
;
863 ret
= sizeof(location_function_comm
) +
864 location_function_comm
.function_name_len
+
865 location_function_comm
.binary_path_len
;
871 int lttng_userspace_probe_location_tracepoint_serialize(
872 const struct lttng_userspace_probe_location
*location
,
873 struct lttng_dynamic_buffer
*buffer
,
877 size_t probe_name_len
, provider_name_len
, binary_path_len
;
878 struct lttng_userspace_probe_location_tracepoint
*location_tracepoint
;
879 struct lttng_userspace_probe_location_tracepoint_comm location_tracepoint_comm
;
882 assert(lttng_userspace_probe_location_get_type(location
) ==
883 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
);
885 location_tracepoint
= container_of(location
,
886 struct lttng_userspace_probe_location_tracepoint
,
888 if (!location_tracepoint
->probe_name
||
889 !location_tracepoint
->provider_name
||
890 !location_tracepoint
->binary_path
) {
891 ret
= -LTTNG_ERR_INVALID
;
895 if (binary_fd
&& location_tracepoint
->binary_fd
< 0) {
896 ret
= -LTTNG_ERR_INVALID
;
901 *binary_fd
= location_tracepoint
->binary_fd
;
904 probe_name_len
= strlen(location_tracepoint
->probe_name
);
905 if (probe_name_len
== 0) {
906 ret
= -LTTNG_ERR_INVALID
;
910 provider_name_len
= strlen(location_tracepoint
->provider_name
);
911 if (provider_name_len
== 0) {
912 ret
= -LTTNG_ERR_INVALID
;
916 binary_path_len
= strlen(location_tracepoint
->binary_path
);
917 if (binary_path_len
== 0) {
918 ret
= -LTTNG_ERR_INVALID
;
922 location_tracepoint_comm
.probe_name_len
= probe_name_len
+ 1;
923 location_tracepoint_comm
.provider_name_len
= provider_name_len
+ 1;
924 location_tracepoint_comm
.binary_path_len
= binary_path_len
+ 1;
927 ret
= lttng_dynamic_buffer_append(buffer
,
928 &location_tracepoint_comm
,
929 sizeof(location_tracepoint_comm
));
931 ret
= -LTTNG_ERR_INVALID
;
934 ret
= lttng_dynamic_buffer_append(buffer
,
935 location_tracepoint
->probe_name
,
936 location_tracepoint_comm
.probe_name_len
);
938 ret
= -LTTNG_ERR_INVALID
;
941 ret
= lttng_dynamic_buffer_append(buffer
,
942 location_tracepoint
->provider_name
,
943 location_tracepoint_comm
.provider_name_len
);
945 ret
= -LTTNG_ERR_INVALID
;
948 ret
= lttng_dynamic_buffer_append(buffer
,
949 location_tracepoint
->binary_path
,
950 location_tracepoint_comm
.binary_path_len
);
952 ret
= -LTTNG_ERR_INVALID
;
956 ret
= sizeof(location_tracepoint_comm
) +
957 location_tracepoint_comm
.probe_name_len
+
958 location_tracepoint_comm
.provider_name_len
+
959 location_tracepoint_comm
.binary_path_len
;
965 int lttng_userspace_probe_location_serialize(
966 const struct lttng_userspace_probe_location
*location
,
967 struct lttng_dynamic_buffer
*buffer
,
970 int ret
, buffer_use
= 0;
971 struct lttng_userspace_probe_location_comm location_generic_comm
;
974 ERR("Invalid argument(s)");
975 ret
= -LTTNG_ERR_INVALID
;
979 memset(&location_generic_comm
, 0, sizeof(location_generic_comm
));
981 location_generic_comm
.type
= (int8_t) location
->type
;
983 ret
= lttng_dynamic_buffer_append(buffer
, &location_generic_comm
,
984 sizeof(location_generic_comm
));
989 buffer_use
+= sizeof(location_generic_comm
);
991 switch (lttng_userspace_probe_location_get_type(location
)) {
992 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
993 ret
= lttng_userspace_probe_location_function_serialize(
994 location
, buffer
, binary_fd
);
996 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
997 ret
= lttng_userspace_probe_location_tracepoint_serialize(
998 location
, buffer
, binary_fd
);
1001 ERR("Unsupported probe location type");
1002 ret
= -LTTNG_ERR_INVALID
;
1010 ret
= lttng_userspace_probe_location_lookup_method_serialize(
1011 location
->lookup_method
, buffer
);
1021 int lttng_userspace_probe_location_function_create_from_buffer(
1022 const struct lttng_buffer_view
*buffer
,
1023 struct lttng_userspace_probe_location
**location
)
1025 struct lttng_userspace_probe_location_function_comm
*location_function_comm
;
1026 const char *function_name_src
, *binary_path_src
;
1027 char *function_name
= NULL
, *binary_path
= NULL
;
1031 assert(buffer
->data
);
1034 location_function_comm
=
1035 (struct lttng_userspace_probe_location_function_comm
*) buffer
->data
;
1037 const size_t expected_size
= sizeof(*location_function_comm
) +
1038 location_function_comm
->function_name_len
+
1039 location_function_comm
->binary_path_len
;
1041 if (buffer
->size
< expected_size
) {
1042 ret
= -LTTNG_ERR_INVALID
;
1046 function_name_src
= buffer
->data
+ sizeof(*location_function_comm
);
1047 binary_path_src
= function_name_src
+
1048 location_function_comm
->function_name_len
;
1050 if (function_name_src
[location_function_comm
->function_name_len
- 1] != '\0') {
1051 ret
= -LTTNG_ERR_INVALID
;
1054 if (binary_path_src
[location_function_comm
->binary_path_len
- 1] != '\0') {
1055 ret
= -LTTNG_ERR_INVALID
;
1059 function_name
= lttng_strndup(function_name_src
, LTTNG_SYMBOL_NAME_LEN
);
1060 if (!function_name
) {
1061 PERROR("lttng_strndup");
1065 binary_path
= lttng_strndup(binary_path_src
, LTTNG_PATH_MAX
);
1067 PERROR("lttng_strndup");
1071 *location
= lttng_userspace_probe_location_function_create_no_check(
1072 binary_path
, function_name
, NULL
, false);
1074 ret
= -LTTNG_ERR_INVALID
;
1078 ret
= (int) expected_size
;
1080 free(function_name
);
1086 int lttng_userspace_probe_location_tracepoint_create_from_buffer(
1087 const struct lttng_buffer_view
*buffer
,
1088 struct lttng_userspace_probe_location
**location
)
1090 struct lttng_userspace_probe_location_tracepoint_comm
*location_tracepoint_comm
;
1091 const char *probe_name_src
, *provider_name_src
, *binary_path_src
;
1092 char *probe_name
= NULL
, *provider_name
= NULL
, *binary_path
= NULL
;
1096 assert(buffer
->data
);
1099 location_tracepoint_comm
=
1100 (struct lttng_userspace_probe_location_tracepoint_comm
*) buffer
->data
;
1102 const size_t expected_size
= sizeof(*location_tracepoint_comm
) +
1103 location_tracepoint_comm
->probe_name_len
+
1104 location_tracepoint_comm
->provider_name_len
+
1105 location_tracepoint_comm
->binary_path_len
;
1107 if (buffer
->size
< expected_size
) {
1108 ret
= -LTTNG_ERR_INVALID
;
1112 probe_name_src
= buffer
->data
+ sizeof(*location_tracepoint_comm
);
1113 provider_name_src
= probe_name_src
+
1114 location_tracepoint_comm
->probe_name_len
;
1115 binary_path_src
= provider_name_src
+
1116 location_tracepoint_comm
->provider_name_len
;
1118 if (probe_name_src
[location_tracepoint_comm
->probe_name_len
- 1] != '\0') {
1119 ret
= -LTTNG_ERR_INVALID
;
1123 if (provider_name_src
[location_tracepoint_comm
->provider_name_len
- 1] != '\0') {
1124 ret
= -LTTNG_ERR_INVALID
;
1128 if (binary_path_src
[location_tracepoint_comm
->binary_path_len
- 1] != '\0') {
1129 ret
= -LTTNG_ERR_INVALID
;
1133 probe_name
= lttng_strndup(probe_name_src
, LTTNG_SYMBOL_NAME_LEN
);
1135 PERROR("lttng_strndup");
1138 provider_name
= lttng_strndup(provider_name_src
, LTTNG_SYMBOL_NAME_LEN
);
1139 if (!provider_name
) {
1140 PERROR("lttng_strndup");
1144 binary_path
= lttng_strndup(binary_path_src
, LTTNG_SYMBOL_NAME_LEN
);
1146 PERROR("lttng_strndup");
1150 *location
= lttng_userspace_probe_location_tracepoint_create_no_check(
1151 binary_path
, provider_name
, probe_name
, NULL
, false);
1153 ret
= -LTTNG_ERR_INVALID
;
1157 ret
= (int) expected_size
;
1160 free(provider_name
);
1166 int lttng_userspace_probe_location_lookup_method_create_from_buffer(
1167 struct lttng_buffer_view
*buffer
,
1168 struct lttng_userspace_probe_location_lookup_method
**lookup_method
)
1171 struct lttng_userspace_probe_location_lookup_method_comm
*lookup_comm
;
1172 enum lttng_userspace_probe_location_lookup_method_type type
;
1175 assert(buffer
->data
);
1176 assert(lookup_method
);
1178 if (buffer
->size
< sizeof(*lookup_comm
)) {
1179 ret
= -LTTNG_ERR_INVALID
;
1183 lookup_comm
= (struct lttng_userspace_probe_location_lookup_method_comm
*)
1185 type
= (enum lttng_userspace_probe_location_lookup_method_type
)
1188 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT
:
1189 *lookup_method
= NULL
;
1191 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
:
1193 lttng_userspace_probe_location_lookup_method_function_elf_create();
1194 if (!(*lookup_method
)) {
1195 ret
= -LTTNG_ERR_INVALID
;
1199 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
:
1201 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1202 if (!(*lookup_method
)) {
1203 ret
= -LTTNG_ERR_INVALID
;
1208 ret
= -LTTNG_ERR_INVALID
;
1212 ret
= sizeof(*lookup_comm
);
1218 int lttng_userspace_probe_location_create_from_buffer(
1219 const struct lttng_buffer_view
*buffer
,
1220 struct lttng_userspace_probe_location
**location
)
1222 struct lttng_userspace_probe_location_lookup_method
*lookup_method
;
1223 struct lttng_userspace_probe_location_comm
*probe_location_comm
;
1224 enum lttng_userspace_probe_location_type type
;
1225 struct lttng_buffer_view lookup_method_view
;
1231 assert(buffer
->data
);
1234 lookup_method
= NULL
;
1236 if (buffer
->size
<= sizeof(*probe_location_comm
)) {
1237 ret
= -LTTNG_ERR_INVALID
;
1241 probe_location_comm
=
1242 (struct lttng_userspace_probe_location_comm
*) buffer
->data
;
1243 type
= (enum lttng_userspace_probe_location_type
) probe_location_comm
->type
;
1244 consumed
+= sizeof(*probe_location_comm
);
1247 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
1249 struct lttng_buffer_view view
= lttng_buffer_view_from_view(
1250 buffer
, consumed
, buffer
->size
- consumed
);
1252 ret
= lttng_userspace_probe_location_function_create_from_buffer(
1259 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
1261 struct lttng_buffer_view view
= lttng_buffer_view_from_view(
1262 buffer
, consumed
, buffer
->size
- consumed
);
1264 ret
= lttng_userspace_probe_location_tracepoint_create_from_buffer(
1272 ret
= -LTTNG_ERR_INVALID
;
1277 if (buffer
->size
<= consumed
) {
1278 ret
= -LTTNG_ERR_INVALID
;
1282 lookup_method_view
= lttng_buffer_view_from_view(buffer
, consumed
,
1283 buffer
->size
- consumed
);
1284 ret
= lttng_userspace_probe_location_lookup_method_create_from_buffer(
1285 &lookup_method_view
, &lookup_method
);
1287 ret
= -LTTNG_ERR_INVALID
;
1291 assert(lookup_method
);
1292 (*location
)->lookup_method
= lookup_method
;
1293 lookup_method
= NULL
;
1300 int lttng_userspace_probe_location_function_set_binary_fd(
1301 struct lttng_userspace_probe_location
*location
, int binary_fd
)
1304 struct lttng_userspace_probe_location_function
*function_location
;
1307 assert(location
->type
== LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
);
1309 function_location
= container_of(location
,
1310 struct lttng_userspace_probe_location_function
, parent
);
1311 if (function_location
->binary_fd
>= 0) {
1312 ret
= close(function_location
->binary_fd
);
1315 ret
= -LTTNG_ERR_INVALID
;
1320 function_location
->binary_fd
= binary_fd
;
1326 int lttng_userspace_probe_location_tracepoint_set_binary_fd(
1327 struct lttng_userspace_probe_location
*location
, int binary_fd
)
1330 struct lttng_userspace_probe_location_tracepoint
*tracepoint_location
;
1333 assert(location
->type
== LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
);
1335 tracepoint_location
= container_of(location
,
1336 struct lttng_userspace_probe_location_tracepoint
, parent
);
1337 if (tracepoint_location
->binary_fd
>= 0) {
1338 ret
= close(tracepoint_location
->binary_fd
);
1341 ret
= -LTTNG_ERR_INVALID
;
1346 tracepoint_location
->binary_fd
= binary_fd
;
1352 int lttng_userspace_probe_location_function_flatten(
1353 const struct lttng_userspace_probe_location
*location
,
1354 struct lttng_dynamic_buffer
*buffer
)
1356 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method
;
1357 struct lttng_userspace_probe_location_function
*probe_function
;
1358 struct lttng_userspace_probe_location_function flat_probe
;
1359 size_t function_name_len
, binary_path_len
;
1360 size_t padding_needed
= 0;
1361 char *flat_probe_start
;
1362 int storage_needed
= 0;
1367 if (location
->lookup_method
&& location
->lookup_method
->type
!=
1368 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
) {
1369 ret
= -LTTNG_ERR_INVALID
;
1373 probe_function
= container_of(location
,
1374 struct lttng_userspace_probe_location_function
,
1376 assert(probe_function
->function_name
);
1377 assert(probe_function
->binary_path
);
1380 sizeof(struct lttng_userspace_probe_location_function
);
1381 function_name_len
= strlen(probe_function
->function_name
) + 1;
1382 binary_path_len
= strlen(probe_function
->binary_path
) + 1;
1383 storage_needed
+= function_name_len
+ binary_path_len
;
1386 * The lookup method is aligned to 64-bit within the buffer.
1387 * This is needed even if there is no lookup method since
1388 * the next structure in the buffer probably needs to be
1389 * aligned too (depending on the arch).
1391 padding_needed
= ALIGN_TO(storage_needed
, sizeof(uint64_t)) - storage_needed
;
1392 storage_needed
+= padding_needed
;
1394 if (location
->lookup_method
) {
1395 /* NOTE: elf look-up method is assumed here. */
1396 storage_needed
+= sizeof(struct lttng_userspace_probe_location_lookup_method_elf
);
1400 ret
= storage_needed
;
1404 if (lttng_dynamic_buffer_get_capacity_left(buffer
) < storage_needed
) {
1405 ret
= lttng_dynamic_buffer_set_capacity(buffer
,
1406 buffer
->size
+ storage_needed
);
1412 memset(&flat_probe
, 0, sizeof(flat_probe
));
1414 flat_probe_start
= buffer
->data
+ buffer
->size
;
1415 flat_probe
.parent
.type
= location
->type
;
1417 * The lookup method, if present, is the last element in the flat
1418 * representation of the probe.
1420 if (location
->lookup_method
) {
1421 flat_probe
.parent
.lookup_method
=
1422 (struct lttng_userspace_probe_location_lookup_method
*)
1423 (flat_probe_start
+ sizeof(flat_probe
) +
1424 function_name_len
+ binary_path_len
+ padding_needed
);
1426 flat_probe
.parent
.lookup_method
= NULL
;
1429 flat_probe
.function_name
= flat_probe_start
+ sizeof(flat_probe
);
1430 flat_probe
.binary_path
= flat_probe
.function_name
+ function_name_len
;
1431 flat_probe
.binary_fd
= -1;
1432 ret
= lttng_dynamic_buffer_append(buffer
, &flat_probe
,
1433 sizeof(flat_probe
));
1438 ret
= lttng_dynamic_buffer_append(buffer
,
1439 probe_function
->function_name
, function_name_len
);
1443 ret
= lttng_dynamic_buffer_append(buffer
,
1444 probe_function
->binary_path
, binary_path_len
);
1449 /* Insert padding before the lookup method. */
1450 ret
= lttng_dynamic_buffer_set_size(buffer
,
1451 buffer
->size
+ padding_needed
);
1456 if (!location
->lookup_method
) {
1457 /* Not an error, the default method is used. */
1458 ret
= storage_needed
;
1462 memset(&flat_lookup_method
, 0, sizeof(flat_lookup_method
));
1463 flat_lookup_method
.parent
.type
=
1464 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF
;
1465 ret
= lttng_dynamic_buffer_append(buffer
,
1466 &flat_lookup_method
, sizeof(flat_lookup_method
));
1470 ret
= storage_needed
;
1476 int lttng_userspace_probe_location_tracepoint_flatten(
1477 const struct lttng_userspace_probe_location
*location
,
1478 struct lttng_dynamic_buffer
*buffer
)
1480 struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method
;
1481 struct lttng_userspace_probe_location_tracepoint
*probe_tracepoint
;
1482 struct lttng_userspace_probe_location_tracepoint flat_probe
;
1483 size_t probe_name_len
, provider_name_len
, binary_path_len
;
1484 size_t padding_needed
= 0;
1485 int storage_needed
= 0;
1486 char *flat_probe_start
;
1491 /* Only SDT tracepoints are supported at the moment */
1492 if (location
->lookup_method
&& location
->lookup_method
->type
!=
1493 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
) {
1494 ret
= -LTTNG_ERR_INVALID
;
1497 probe_tracepoint
= container_of(location
,
1498 struct lttng_userspace_probe_location_tracepoint
,
1500 assert(probe_tracepoint
->probe_name
);
1501 assert(probe_tracepoint
->provider_name
);
1502 assert(probe_tracepoint
->binary_path
);
1504 /* Compute the storage space needed to flatten the probe location */
1505 storage_needed
+= sizeof(struct lttng_userspace_probe_location_tracepoint
);
1507 probe_name_len
= strlen(probe_tracepoint
->probe_name
) + 1;
1508 provider_name_len
= strlen(probe_tracepoint
->provider_name
) + 1;
1509 binary_path_len
= strlen(probe_tracepoint
->binary_path
) + 1;
1511 storage_needed
+= probe_name_len
+ provider_name_len
+ binary_path_len
;
1514 * The lookup method is aligned to 64-bit within the buffer.
1515 * This is needed even if there is no lookup method since
1516 * the next structure in the buffer probably needs to be
1517 * aligned too (depending on the arch).
1519 padding_needed
= ALIGN_TO(storage_needed
, sizeof(uint64_t)) - storage_needed
;
1520 storage_needed
+= padding_needed
;
1522 if (location
->lookup_method
) {
1523 /* NOTE: elf look-up method is assumed here. */
1525 sizeof(struct lttng_userspace_probe_location_lookup_method_elf
);
1529 * If the caller set buffer to NULL, return the size of the needed buffer.
1532 ret
= storage_needed
;
1536 if (lttng_dynamic_buffer_get_capacity_left(buffer
) < storage_needed
) {
1537 ret
= lttng_dynamic_buffer_set_capacity(buffer
,
1538 buffer
->size
+ storage_needed
);
1544 memset(&flat_probe
, 0, sizeof(flat_probe
));
1546 flat_probe_start
= buffer
->data
+ buffer
->size
;
1547 flat_probe
.parent
.type
= location
->type
;
1550 * The lookup method, if present, is the last element in the flat
1551 * representation of the probe.
1553 if (location
->lookup_method
) {
1554 flat_probe
.parent
.lookup_method
=
1555 (struct lttng_userspace_probe_location_lookup_method
*)
1556 (flat_probe_start
+ sizeof(flat_probe
) +
1557 probe_name_len
+ provider_name_len
+
1558 binary_path_len
+ padding_needed
);
1560 flat_probe
.parent
.lookup_method
= NULL
;
1563 flat_probe
.probe_name
= flat_probe_start
+ sizeof(flat_probe
);
1564 flat_probe
.provider_name
= flat_probe
.probe_name
+ probe_name_len
;
1565 flat_probe
.binary_path
= flat_probe
.provider_name
+ provider_name_len
;
1566 flat_probe
.binary_fd
= -1;
1567 ret
= lttng_dynamic_buffer_append(buffer
, &flat_probe
, sizeof(flat_probe
));
1572 /* Append all the fields to the buffer */
1573 ret
= lttng_dynamic_buffer_append(buffer
,
1574 probe_tracepoint
->probe_name
, probe_name_len
);
1578 ret
= lttng_dynamic_buffer_append(buffer
,
1579 probe_tracepoint
->provider_name
, provider_name_len
);
1583 ret
= lttng_dynamic_buffer_append(buffer
,
1584 probe_tracepoint
->binary_path
, binary_path_len
);
1589 /* Insert padding before the lookup method. */
1590 ret
= lttng_dynamic_buffer_set_size(buffer
, buffer
->size
+ padding_needed
);
1595 if (!location
->lookup_method
) {
1596 /* Not an error, the default method is used. */
1597 ret
= storage_needed
;
1601 memset(&flat_lookup_method
, 0, sizeof(flat_lookup_method
));
1603 flat_lookup_method
.parent
.type
=
1604 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT
;
1605 ret
= lttng_dynamic_buffer_append(buffer
,
1606 &flat_lookup_method
, sizeof(flat_lookup_method
));
1610 ret
= storage_needed
;
1616 int lttng_userspace_probe_location_flatten(
1617 const struct lttng_userspace_probe_location
*location
,
1618 struct lttng_dynamic_buffer
*buffer
)
1622 ret
= -LTTNG_ERR_INVALID
;
1626 /* Only types currently supported. */
1627 switch (location
->type
) {
1628 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
1629 ret
= lttng_userspace_probe_location_function_flatten(location
, buffer
);
1631 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
1632 ret
= lttng_userspace_probe_location_tracepoint_flatten(location
, buffer
);
1635 ret
= -LTTNG_ERR_INVALID
;
1644 struct lttng_userspace_probe_location
*lttng_userspace_probe_location_copy(
1645 const struct lttng_userspace_probe_location
*location
)
1647 struct lttng_userspace_probe_location
*new_location
= NULL
;
1648 enum lttng_userspace_probe_location_type type
;
1654 type
= lttng_userspace_probe_location_get_type(location
);
1656 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION
:
1658 lttng_userspace_probe_location_function_copy(location
);
1659 if (!new_location
) {
1663 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT
:
1665 lttng_userspace_probe_location_tracepoint_copy(location
);
1666 if (!new_location
) {
1671 new_location
= NULL
;
1675 return new_location
;