Add vendor/fmt
[lttng-tools.git] / src / common / userspace-probe.cpp
1 /*
2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include "lttng/lttng-error.h"
9 #include <common/compat/string.hpp>
10 #include <common/align.hpp>
11 #include <common/error.hpp>
12 #include <common/hashtable/hashtable.hpp>
13 #include <common/hashtable/utils.hpp>
14 #include <common/macros.hpp>
15 #include <common/mi-lttng.hpp>
16 #include <common/payload-view.hpp>
17 #include <common/payload.hpp>
18 #include <fcntl.h>
19 #include <lttng/constant.h>
20 #include <lttng/userspace-probe-internal.hpp>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24
25 static
26 int lttng_userspace_probe_location_function_set_binary_fd_handle(
27 struct lttng_userspace_probe_location *location,
28 struct fd_handle *binary_fd_handle);
29
30 static
31 int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
32 struct lttng_userspace_probe_location *location,
33 struct fd_handle *binary_fd_handle);
34
35 static
36 enum lttng_error_code lttng_userspace_probe_location_lookup_method_mi_serialize(
37 const struct lttng_userspace_probe_location_lookup_method
38 *method,
39 struct mi_writer *writer);
40
41 static
42 enum lttng_error_code lttng_userspace_probe_location_tracepoint_mi_serialize(
43 const struct lttng_userspace_probe_location *location,
44 struct mi_writer *writer);
45
46 static
47 enum lttng_error_code lttng_userspace_probe_location_function_mi_serialize(
48 const struct lttng_userspace_probe_location *location,
49 struct mi_writer *writer);
50
51 enum lttng_userspace_probe_location_lookup_method_type
52 lttng_userspace_probe_location_lookup_method_get_type(
53 const struct lttng_userspace_probe_location_lookup_method *lookup_method)
54 {
55 return lookup_method ? lookup_method->type :
56 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_UNKNOWN;
57 }
58
59 void lttng_userspace_probe_location_lookup_method_destroy(
60 struct lttng_userspace_probe_location_lookup_method *lookup_method)
61 {
62 if (!lookup_method){
63 return;
64 }
65
66 free(lookup_method);
67 }
68
69 struct lttng_userspace_probe_location_lookup_method *
70 lttng_userspace_probe_location_lookup_method_function_elf_create(void)
71 {
72 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
73 struct lttng_userspace_probe_location_lookup_method_elf *elf_method;
74
75 elf_method = zmalloc<lttng_userspace_probe_location_lookup_method_elf>();
76 if (!elf_method) {
77 PERROR("zmalloc");
78 goto end;
79 }
80
81 ret = &elf_method->parent;
82 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
83 end:
84 return ret;
85 }
86
87 struct lttng_userspace_probe_location_lookup_method *
88 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create(void)
89 {
90 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
91 struct lttng_userspace_probe_location_lookup_method_sdt *sdt_method;
92
93 sdt_method = zmalloc<lttng_userspace_probe_location_lookup_method_sdt>();
94 if (!sdt_method) {
95 PERROR("zmalloc");
96 goto end;
97 }
98
99 ret = &sdt_method->parent;
100 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
101 end:
102 return ret;
103 }
104
105 enum lttng_userspace_probe_location_type lttng_userspace_probe_location_get_type(
106 const struct lttng_userspace_probe_location *location)
107 {
108 return location ? location->type :
109 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN;
110 }
111
112 static
113 void lttng_userspace_probe_location_function_destroy(
114 struct lttng_userspace_probe_location *location)
115 {
116 struct lttng_userspace_probe_location_function *location_function = NULL;
117
118 LTTNG_ASSERT(location);
119
120 location_function = container_of(location,
121 struct lttng_userspace_probe_location_function, parent);
122
123 LTTNG_ASSERT(location_function);
124
125 free(location_function->function_name);
126 free(location_function->binary_path);
127 fd_handle_put(location_function->binary_fd_handle);
128 free(location);
129 }
130
131 static
132 void lttng_userspace_probe_location_tracepoint_destroy(
133 struct lttng_userspace_probe_location *location)
134 {
135 struct lttng_userspace_probe_location_tracepoint *location_tracepoint = NULL;
136
137 LTTNG_ASSERT(location);
138
139 location_tracepoint = container_of(location,
140 struct lttng_userspace_probe_location_tracepoint,
141 parent);
142
143 LTTNG_ASSERT(location_tracepoint);
144
145 free(location_tracepoint->probe_name);
146 free(location_tracepoint->provider_name);
147 free(location_tracepoint->binary_path);
148 fd_handle_put(location_tracepoint->binary_fd_handle);
149 free(location);
150 }
151
152 void lttng_userspace_probe_location_destroy(
153 struct lttng_userspace_probe_location *location)
154 {
155 if (!location) {
156 return;
157 }
158
159 lttng_userspace_probe_location_lookup_method_destroy(
160 location->lookup_method);
161
162 switch (location->type) {
163 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
164 lttng_userspace_probe_location_function_destroy(location);
165 break;
166 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
167 lttng_userspace_probe_location_tracepoint_destroy(location);
168 break;
169 default:
170 abort();
171 }
172 }
173
174 /* Compare two file descriptors based on their inode and device numbers. */
175 static bool fd_is_equal(int a, int b)
176 {
177 int ret;
178 bool is_equal = false;
179 struct stat a_stat, b_stat;
180
181 if (a < 0 && b >= 0) {
182 goto end;
183 }
184
185 if (b < 0 && a >= 0) {
186 goto end;
187 }
188
189 if (a < 0 && b < 0) {
190 if (a == -1 && b == -1) {
191 is_equal = true;
192 goto end;
193 }
194
195 /* Invalid state, abort. */
196 abort();
197 }
198
199 /* Both are valid file descriptors. */
200 ret = fstat(a, &a_stat);
201 if (ret) {
202 PERROR("Failed to fstat userspace probe location binary fd %d",
203 a);
204 goto end;
205 }
206
207 ret = fstat(b, &b_stat);
208 if (ret) {
209 PERROR("Failed to fstat userspace probe location binary fd %d",
210 b);
211 goto end;
212 }
213
214 is_equal = (a_stat.st_ino == b_stat.st_ino) &&
215 (a_stat.st_dev == b_stat.st_dev);
216
217 end:
218 return is_equal;
219 }
220
221 static unsigned long lttng_userspace_probe_location_function_hash(
222 const struct lttng_userspace_probe_location *location)
223 {
224 unsigned long hash = hash_key_ulong(
225 (void *) LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION,
226 lttng_ht_seed);
227 struct lttng_userspace_probe_location_function *function_location =
228 container_of(location, typeof(*function_location),
229 parent);
230
231 hash ^= hash_key_str(function_location->function_name, lttng_ht_seed);
232 hash ^= hash_key_str(function_location->binary_path, lttng_ht_seed);
233 /*
234 * No need to hash on the fd. Worst comes to worse,
235 * the equal function will discriminate.
236 */
237 return hash;
238 }
239
240 static bool lttng_userspace_probe_location_function_is_equal(
241 const struct lttng_userspace_probe_location *_a,
242 const struct lttng_userspace_probe_location *_b)
243 {
244 bool is_equal = false;
245 struct lttng_userspace_probe_location_function *a, *b;
246
247 a = container_of(_a, struct lttng_userspace_probe_location_function,
248 parent);
249 b = container_of(_b, struct lttng_userspace_probe_location_function,
250 parent);
251
252 if (a->instrumentation_type != b->instrumentation_type) {
253 goto end;
254 }
255
256 LTTNG_ASSERT(a->function_name);
257 LTTNG_ASSERT(b->function_name);
258 if (strcmp(a->function_name, b->function_name)) {
259 goto end;
260 }
261
262 LTTNG_ASSERT(a->binary_path);
263 LTTNG_ASSERT(b->binary_path);
264 if (strcmp(a->binary_path, b->binary_path)) {
265 goto end;
266 }
267
268 is_equal = fd_is_equal(a->binary_fd_handle ? fd_handle_get_fd(a->binary_fd_handle) : -1,
269 b->binary_fd_handle ? fd_handle_get_fd(b->binary_fd_handle) : -1);
270 end:
271 return is_equal;
272 }
273
274 static struct lttng_userspace_probe_location *
275 lttng_userspace_probe_location_function_create_no_check(const char *binary_path,
276 const char *function_name,
277 struct lttng_userspace_probe_location_lookup_method *lookup_method,
278 bool open_binary)
279 {
280 int binary_fd = -1;
281 struct fd_handle *binary_fd_handle = NULL;
282 char *function_name_copy = NULL, *binary_path_copy = NULL;
283 struct lttng_userspace_probe_location *ret = NULL;
284 struct lttng_userspace_probe_location_function *location;
285
286 if (open_binary) {
287 binary_fd = open(binary_path, O_RDONLY);
288 if (binary_fd < 0) {
289 PERROR("Error opening the binary");
290 goto error;
291 }
292
293 binary_fd_handle = fd_handle_create(binary_fd);
294 if (!binary_fd) {
295 goto error;
296 }
297
298 /* Ownership transferred to fd_handle. */
299 binary_fd = -1;
300 }
301
302 function_name_copy = lttng_strndup(function_name, LTTNG_SYMBOL_NAME_LEN);
303 if (!function_name_copy) {
304 PERROR("Error duplicating the function name");
305 goto error;
306 }
307
308 binary_path_copy = lttng_strndup(binary_path, LTTNG_PATH_MAX);
309 if (!binary_path_copy) {
310 PERROR("Error duplicating the function name");
311 goto error;
312 }
313
314 location = zmalloc<lttng_userspace_probe_location_function>();
315 if (!location) {
316 PERROR("Error allocating userspace probe location");
317 goto error;
318 }
319
320 location->function_name = function_name_copy;
321 location->binary_path = binary_path_copy;
322 location->binary_fd_handle = binary_fd_handle;
323 binary_fd_handle = NULL;
324 location->instrumentation_type =
325 LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY;
326
327 ret = &location->parent;
328 ret->lookup_method = lookup_method;
329 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION;
330 ret->equal = lttng_userspace_probe_location_function_is_equal;
331 ret->hash = lttng_userspace_probe_location_function_hash;
332 goto end;
333
334 error:
335 free(function_name_copy);
336 free(binary_path_copy);
337 if (binary_fd >= 0) {
338 if (close(binary_fd)) {
339 PERROR("Error closing binary fd in error path");
340 }
341 }
342 fd_handle_put(binary_fd_handle);
343 end:
344 return ret;
345 }
346
347 static unsigned long lttng_userspace_probe_location_tracepoint_hash(
348 const struct lttng_userspace_probe_location *location)
349 {
350 unsigned long hash = hash_key_ulong(
351 (void *) LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT,
352 lttng_ht_seed);
353 struct lttng_userspace_probe_location_tracepoint *tp_location =
354 container_of(location, typeof(*tp_location), parent);
355
356 hash ^= hash_key_str(tp_location->probe_name, lttng_ht_seed);
357 hash ^= hash_key_str(tp_location->provider_name, lttng_ht_seed);
358 hash ^= hash_key_str(tp_location->binary_path, lttng_ht_seed);
359 /*
360 * No need to hash on the fd. Worst comes to worse,
361 * the equal function will discriminate.
362 */
363 return hash;
364 }
365
366 static bool lttng_userspace_probe_location_tracepoint_is_equal(
367 const struct lttng_userspace_probe_location *_a,
368 const struct lttng_userspace_probe_location *_b)
369 {
370 bool is_equal = false;
371 struct lttng_userspace_probe_location_tracepoint *a, *b;
372
373 a = container_of(_a, struct lttng_userspace_probe_location_tracepoint,
374 parent);
375 b = container_of(_b, struct lttng_userspace_probe_location_tracepoint,
376 parent);
377
378 LTTNG_ASSERT(a->probe_name);
379 LTTNG_ASSERT(b->probe_name);
380 if (strcmp(a->probe_name, b->probe_name)) {
381 goto end;
382 }
383
384 LTTNG_ASSERT(a->provider_name);
385 LTTNG_ASSERT(b->provider_name);
386 if (strcmp(a->provider_name, b->provider_name)) {
387 goto end;
388 }
389
390 LTTNG_ASSERT(a->binary_path);
391 LTTNG_ASSERT(b->binary_path);
392 if (strcmp(a->binary_path, b->binary_path)) {
393 goto end;
394 }
395
396 is_equal = fd_is_equal(a->binary_fd_handle ? fd_handle_get_fd(a->binary_fd_handle) : -1,
397 b->binary_fd_handle ? fd_handle_get_fd(b->binary_fd_handle) : -1);
398
399 end:
400 return is_equal;
401 }
402
403 static struct lttng_userspace_probe_location *
404 lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_path,
405 const char *provider_name, const char *probe_name,
406 struct lttng_userspace_probe_location_lookup_method *lookup_method,
407 bool open_binary)
408 {
409 int binary_fd = -1;
410 struct fd_handle *binary_fd_handle = NULL;
411 char *probe_name_copy = NULL;
412 char *provider_name_copy = NULL;
413 char *binary_path_copy = NULL;
414 struct lttng_userspace_probe_location *ret = NULL;
415 struct lttng_userspace_probe_location_tracepoint *location;
416
417 if (open_binary) {
418 binary_fd = open(binary_path, O_RDONLY);
419 if (binary_fd < 0) {
420 PERROR("open");
421 goto error;
422 }
423
424 binary_fd_handle = fd_handle_create(binary_fd);
425 if (!binary_fd) {
426 goto error;
427 }
428
429 /* Ownership transferred to fd_handle. */
430 binary_fd = -1;
431 }
432
433 probe_name_copy = lttng_strndup(probe_name, LTTNG_SYMBOL_NAME_LEN);
434 if (!probe_name_copy) {
435 PERROR("lttng_strndup");
436 goto error;
437 }
438
439 provider_name_copy = lttng_strndup(provider_name, LTTNG_SYMBOL_NAME_LEN);
440 if (!provider_name_copy) {
441 PERROR("lttng_strndup");
442 goto error;
443 }
444
445 binary_path_copy = lttng_strndup(binary_path, LTTNG_PATH_MAX);
446 if (!binary_path_copy) {
447 PERROR("lttng_strndup");
448 goto error;
449 }
450
451 location = zmalloc<lttng_userspace_probe_location_tracepoint>();
452 if (!location) {
453 PERROR("zmalloc");
454 goto error;
455 }
456
457 location->probe_name = probe_name_copy;
458 location->provider_name = provider_name_copy;
459 location->binary_path = binary_path_copy;
460 location->binary_fd_handle = binary_fd_handle;
461 binary_fd_handle = NULL;
462
463 ret = &location->parent;
464 ret->lookup_method = lookup_method;
465 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT;
466 ret->equal = lttng_userspace_probe_location_tracepoint_is_equal;
467 ret->hash = lttng_userspace_probe_location_tracepoint_hash;
468 goto end;
469
470 error:
471 free(probe_name_copy);
472 free(provider_name_copy);
473 free(binary_path_copy);
474 if (binary_fd >= 0) {
475 if (close(binary_fd)) {
476 PERROR("Error closing binary fd in error path");
477 }
478 }
479 fd_handle_put(binary_fd_handle);
480 end:
481 return ret;
482 }
483
484 struct lttng_userspace_probe_location *
485 lttng_userspace_probe_location_function_create(const char *binary_path,
486 const char *function_name,
487 struct lttng_userspace_probe_location_lookup_method *lookup_method)
488 {
489 struct lttng_userspace_probe_location *ret = NULL;
490
491 if (!binary_path || !function_name) {
492 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
493 goto end;
494 }
495
496 switch (lttng_userspace_probe_location_lookup_method_get_type(
497 lookup_method)) {
498 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
499 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
500 break;
501 default:
502 /* Invalid probe location lookup method. */
503 goto end;
504 }
505
506 ret = lttng_userspace_probe_location_function_create_no_check(
507 binary_path, function_name, lookup_method, true);
508 end:
509 return ret;
510 }
511
512 struct lttng_userspace_probe_location *
513 lttng_userspace_probe_location_tracepoint_create(const char *binary_path,
514 const char *provider_name, const char *probe_name,
515 struct lttng_userspace_probe_location_lookup_method *lookup_method)
516 {
517 struct lttng_userspace_probe_location *ret = NULL;
518
519 if (!binary_path || !probe_name || !provider_name) {
520 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
521 goto end;
522 }
523
524 switch (lttng_userspace_probe_location_lookup_method_get_type(
525 lookup_method)) {
526 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
527 break;
528 default:
529 /* Invalid probe location lookup method. */
530 goto end;
531 }
532
533 ret = lttng_userspace_probe_location_tracepoint_create_no_check(
534 binary_path, provider_name, probe_name, lookup_method, true);
535 end:
536 return ret;
537 }
538
539 static struct lttng_userspace_probe_location_lookup_method *
540 lttng_userspace_probe_location_lookup_method_function_elf_copy(
541 const struct lttng_userspace_probe_location_lookup_method *lookup_method)
542 {
543 struct lttng_userspace_probe_location_lookup_method *parent = NULL;
544 struct lttng_userspace_probe_location_lookup_method_elf *elf_method;
545
546 LTTNG_ASSERT(lookup_method);
547 LTTNG_ASSERT(lookup_method->type ==
548 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF);
549
550 elf_method = zmalloc<lttng_userspace_probe_location_lookup_method_elf>();
551 if (!elf_method) {
552 PERROR("Error allocating ELF userspace probe lookup method");
553 goto error;
554 }
555
556 elf_method->parent.type = lookup_method->type;
557 parent = &elf_method->parent;
558
559 goto end;
560 error:
561 parent = NULL;
562 end:
563 return parent;
564 }
565
566 static struct lttng_userspace_probe_location_lookup_method *
567 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
568 struct lttng_userspace_probe_location_lookup_method *lookup_method)
569 {
570 struct lttng_userspace_probe_location_lookup_method *parent = NULL;
571 struct lttng_userspace_probe_location_lookup_method_sdt *sdt_method;
572
573 LTTNG_ASSERT(lookup_method);
574 LTTNG_ASSERT(lookup_method->type ==
575 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT);
576
577 sdt_method = zmalloc<lttng_userspace_probe_location_lookup_method_sdt>();
578 if (!sdt_method) {
579 PERROR("zmalloc");
580 goto error;
581 }
582
583 sdt_method->parent.type = lookup_method->type;
584 parent = &sdt_method->parent;
585
586 goto end;
587
588 error:
589 parent = NULL;
590 end:
591 return parent;
592 }
593
594 static struct lttng_userspace_probe_location *
595 lttng_userspace_probe_location_function_copy(
596 const struct lttng_userspace_probe_location *location)
597 {
598 enum lttng_userspace_probe_location_lookup_method_type lookup_type;
599 struct lttng_userspace_probe_location *new_location = NULL;
600 struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
601 const char *binary_path = NULL;
602 const char *function_name = NULL;
603 struct lttng_userspace_probe_location_function *function_location;
604
605 LTTNG_ASSERT(location);
606 LTTNG_ASSERT(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
607 function_location = container_of(
608 location, typeof(*function_location), parent);
609
610 /* Get probe location fields */
611 binary_path = lttng_userspace_probe_location_function_get_binary_path(location);
612 if (!binary_path) {
613 ERR("Userspace probe binary path is NULL");
614 goto error;
615 }
616
617 function_name = lttng_userspace_probe_location_function_get_function_name(location);
618 if (!function_name) {
619 ERR("Userspace probe function name is NULL");
620 goto error;
621 }
622
623 /*
624 * Duplicate probe location method fields
625 */
626 lookup_type = lttng_userspace_probe_location_lookup_method_get_type(
627 location->lookup_method);
628 switch (lookup_type) {
629 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
630 lookup_method =
631 lttng_userspace_probe_location_lookup_method_function_elf_copy(
632 location->lookup_method);
633 if (!lookup_method) {
634 goto error;
635 }
636 break;
637 default:
638 /* Invalid probe location lookup method. */
639 goto error;
640 }
641
642 /* Create the probe_location */
643 new_location = lttng_userspace_probe_location_function_create_no_check(
644 binary_path, function_name, lookup_method, false);
645 if (!new_location) {
646 goto destroy_lookup_method;
647 }
648
649 /* Set the duplicated fd to the new probe_location */
650 if (lttng_userspace_probe_location_function_set_binary_fd_handle(new_location,
651 function_location->binary_fd_handle) < 0) {
652 goto destroy_probe_location;
653 }
654
655 goto end;
656
657 destroy_probe_location:
658 lttng_userspace_probe_location_destroy(new_location);
659 destroy_lookup_method:
660 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
661 error:
662 new_location = NULL;
663 end:
664 return new_location;
665 }
666
667 static struct lttng_userspace_probe_location *
668 lttng_userspace_probe_location_tracepoint_copy(
669 const struct lttng_userspace_probe_location *location)
670 {
671 enum lttng_userspace_probe_location_lookup_method_type lookup_type;
672 struct lttng_userspace_probe_location *new_location = NULL;
673 struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
674 const char *binary_path = NULL;
675 const char *probe_name = NULL;
676 const char *provider_name = NULL;
677 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
678
679 LTTNG_ASSERT(location);
680 LTTNG_ASSERT(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
681 tracepoint_location = container_of(
682 location, typeof(*tracepoint_location), parent);
683
684 /* Get probe location fields */
685 binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(location);
686 if (!binary_path) {
687 ERR("Userspace probe binary path is NULL");
688 goto error;
689 }
690
691 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(location);
692 if (!probe_name) {
693 ERR("Userspace probe probe name is NULL");
694 goto error;
695 }
696
697 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(location);
698 if (!provider_name) {
699 ERR("Userspace probe provider name is NULL");
700 goto error;
701 }
702
703 /*
704 * Duplicate probe location method fields
705 */
706 lookup_type = lttng_userspace_probe_location_lookup_method_get_type(
707 location->lookup_method);
708 switch (lookup_type) {
709 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
710 lookup_method =
711 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
712 location->lookup_method);
713 if (!lookup_method) {
714 goto error;
715 }
716 break;
717 default:
718 /* Invalid probe location lookup method. */
719 goto error;
720 }
721
722 /* Create the probe_location */
723 new_location = lttng_userspace_probe_location_tracepoint_create_no_check(
724 binary_path, provider_name, probe_name, lookup_method, false);
725 if (!new_location) {
726 goto destroy_lookup_method;
727 }
728
729 /* Set the duplicated fd to the new probe_location */
730 if (lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(new_location,
731 tracepoint_location->binary_fd_handle) < 0) {
732 goto destroy_probe_location;
733 }
734
735 goto end;
736
737 destroy_probe_location:
738 lttng_userspace_probe_location_destroy(new_location);
739 destroy_lookup_method:
740 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
741 error:
742 new_location = NULL;
743 end:
744 return new_location;
745 }
746
747 const char *lttng_userspace_probe_location_function_get_binary_path(
748 const struct lttng_userspace_probe_location *location)
749 {
750 const char *ret = NULL;
751 struct lttng_userspace_probe_location_function *function_location;
752
753 if (!location || lttng_userspace_probe_location_get_type(location) !=
754 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
755 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
756 goto end;
757 }
758
759 function_location = container_of(location,
760 struct lttng_userspace_probe_location_function,
761 parent);
762 ret = function_location->binary_path;
763 end:
764 return ret;
765 }
766
767 const char *lttng_userspace_probe_location_tracepoint_get_binary_path(
768 const struct lttng_userspace_probe_location *location)
769 {
770 const char *ret = NULL;
771 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
772
773 if (!location || lttng_userspace_probe_location_get_type(location) !=
774 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
775 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
776 goto end;
777 }
778
779 tracepoint_location = container_of(location,
780 struct lttng_userspace_probe_location_tracepoint,
781 parent);
782 ret = tracepoint_location->binary_path;
783 end:
784 return ret;
785 }
786
787 const char *lttng_userspace_probe_location_function_get_function_name(
788 const struct lttng_userspace_probe_location *location)
789 {
790 const char *ret = NULL;
791 struct lttng_userspace_probe_location_function *function_location;
792
793 if (!location || lttng_userspace_probe_location_get_type(location) !=
794 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
795 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
796 goto end;
797 }
798
799 function_location = container_of(location,
800 struct lttng_userspace_probe_location_function, parent);
801 ret = function_location->function_name;
802 end:
803 return ret;
804 }
805
806 const char *lttng_userspace_probe_location_tracepoint_get_probe_name(
807 const struct lttng_userspace_probe_location *location)
808 {
809 const char *ret = NULL;
810 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
811
812 if (!location || lttng_userspace_probe_location_get_type(location) !=
813 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
814 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
815 goto end;
816 }
817
818 tracepoint_location = container_of(location,
819 struct lttng_userspace_probe_location_tracepoint, parent);
820 ret = tracepoint_location->probe_name;
821 end:
822 return ret;
823 }
824
825 const char *lttng_userspace_probe_location_tracepoint_get_provider_name(
826 const struct lttng_userspace_probe_location *location)
827 {
828 const char *ret = NULL;
829 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
830
831 if (!location || lttng_userspace_probe_location_get_type(location) !=
832 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
833 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
834 goto end;
835 }
836
837 tracepoint_location = container_of(location,
838 struct lttng_userspace_probe_location_tracepoint, parent);
839 ret = tracepoint_location->provider_name;
840 end:
841 return ret;
842 }
843
844 int lttng_userspace_probe_location_function_get_binary_fd(
845 const struct lttng_userspace_probe_location *location)
846 {
847 int ret = -1;
848 struct lttng_userspace_probe_location_function *function_location;
849
850 if (!location || lttng_userspace_probe_location_get_type(location) !=
851 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
852 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
853 goto end;
854 }
855
856 function_location = container_of(location,
857 struct lttng_userspace_probe_location_function, parent);
858 ret = function_location->binary_fd_handle ?
859 fd_handle_get_fd(function_location->binary_fd_handle) : -1;
860 end:
861 return ret;
862 }
863
864 enum lttng_userspace_probe_location_function_instrumentation_type
865 lttng_userspace_probe_location_function_get_instrumentation_type(
866 const struct lttng_userspace_probe_location *location)
867 {
868 enum lttng_userspace_probe_location_function_instrumentation_type type;
869 struct lttng_userspace_probe_location_function *function_location;
870
871 if (!location || lttng_userspace_probe_location_get_type(location) !=
872 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
873 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
874 type = LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_UNKNOWN;
875 goto end;
876 }
877
878 function_location = container_of(location,
879 struct lttng_userspace_probe_location_function, parent);
880 type = function_location->instrumentation_type;
881 end:
882 return type;
883 }
884
885 enum lttng_userspace_probe_location_status
886 lttng_userspace_probe_location_function_set_instrumentation_type(
887 const struct lttng_userspace_probe_location *location,
888 enum lttng_userspace_probe_location_function_instrumentation_type instrumentation_type)
889 {
890 enum lttng_userspace_probe_location_status status =
891 LTTNG_USERSPACE_PROBE_LOCATION_STATUS_OK;
892 struct lttng_userspace_probe_location_function *function_location;
893
894 if (!location || lttng_userspace_probe_location_get_type(location) !=
895 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION ||
896 instrumentation_type !=
897 LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY) {
898 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
899 status = LTTNG_USERSPACE_PROBE_LOCATION_STATUS_INVALID;
900 goto end;
901 }
902
903 function_location = container_of(location,
904 struct lttng_userspace_probe_location_function, parent);
905 function_location->instrumentation_type = instrumentation_type;
906 end:
907 return status;
908 }
909
910 int lttng_userspace_probe_location_tracepoint_get_binary_fd(
911 const struct lttng_userspace_probe_location *location)
912 {
913 int ret = -1;
914 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
915
916 if (!location || lttng_userspace_probe_location_get_type(location) !=
917 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
918 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
919 goto end;
920 }
921
922 tracepoint_location = container_of(location,
923 struct lttng_userspace_probe_location_tracepoint, parent);
924 ret = tracepoint_location->binary_fd_handle ?
925 fd_handle_get_fd(tracepoint_location->binary_fd_handle) : -1;
926 end:
927 return ret;
928 }
929
930 static struct lttng_userspace_probe_location_lookup_method *
931 lttng_userspace_probe_location_function_get_lookup_method(
932 const struct lttng_userspace_probe_location *location)
933 {
934 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
935
936 if (!location || lttng_userspace_probe_location_get_type(location) !=
937 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
938 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
939 goto end;
940 }
941
942 ret = location->lookup_method;
943 end:
944 return ret;
945 }
946
947 static struct lttng_userspace_probe_location_lookup_method *
948 lttng_userspace_probe_location_tracepoint_get_lookup_method(
949 const struct lttng_userspace_probe_location *location)
950 {
951 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
952
953 if (!location || lttng_userspace_probe_location_get_type(location) !=
954 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
955 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
956 goto end;
957 }
958
959 ret = location->lookup_method;
960 end:
961 return ret;
962 }
963
964 const struct lttng_userspace_probe_location_lookup_method *
965 lttng_userspace_probe_location_get_lookup_method(
966 const struct lttng_userspace_probe_location *location)
967 {
968 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
969
970 LTTNG_ASSERT(location);
971 switch (location->type) {
972 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
973 ret = lttng_userspace_probe_location_function_get_lookup_method(
974 location);
975 break;
976 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
977 ret = lttng_userspace_probe_location_tracepoint_get_lookup_method(
978 location);
979 break;
980 default:
981 ERR("Unknowned lookup method.");
982 break;
983 }
984 return ret;
985 }
986
987 static
988 int lttng_userspace_probe_location_lookup_method_serialize(
989 struct lttng_userspace_probe_location_lookup_method *method,
990 struct lttng_payload *payload)
991 {
992 int ret;
993 struct lttng_userspace_probe_location_lookup_method_comm
994 lookup_method_comm;
995
996 lookup_method_comm.type = (int8_t) (method ? method->type :
997 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT);
998 if (payload) {
999 ret = lttng_dynamic_buffer_append(&payload->buffer, &lookup_method_comm,
1000 sizeof(lookup_method_comm));
1001 if (ret) {
1002 goto end;
1003 }
1004 }
1005 ret = sizeof(lookup_method_comm);
1006 end:
1007 return ret;
1008 }
1009
1010 static
1011 int lttng_userspace_probe_location_function_serialize(
1012 const struct lttng_userspace_probe_location *location,
1013 struct lttng_payload *payload)
1014 {
1015 int ret;
1016 size_t function_name_len, binary_path_len;
1017 struct lttng_userspace_probe_location_function *location_function;
1018 struct lttng_userspace_probe_location_function_comm location_function_comm;
1019
1020 LTTNG_ASSERT(location);
1021 LTTNG_ASSERT(lttng_userspace_probe_location_get_type(location) ==
1022 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1023
1024 location_function = container_of(location,
1025 struct lttng_userspace_probe_location_function,
1026 parent);
1027 if (!location_function->function_name || !location_function->binary_path) {
1028 ret = -LTTNG_ERR_INVALID;
1029 goto end;
1030 }
1031
1032 if (payload && !location_function->binary_fd_handle) {
1033 ret = -LTTNG_ERR_INVALID;
1034 goto end;
1035 }
1036
1037 function_name_len = strlen(location_function->function_name);
1038 if (function_name_len == 0) {
1039 ret = -LTTNG_ERR_INVALID;
1040 goto end;
1041 }
1042 binary_path_len = strlen(location_function->binary_path);
1043 if (binary_path_len == 0) {
1044 ret = -LTTNG_ERR_INVALID;
1045 goto end;
1046 }
1047
1048 location_function_comm.function_name_len = function_name_len + 1;
1049 location_function_comm.binary_path_len = binary_path_len + 1;
1050
1051 if (payload) {
1052 ret = lttng_dynamic_buffer_append(&payload->buffer,
1053 &location_function_comm,
1054 sizeof(location_function_comm));
1055 if (ret) {
1056 ret = -LTTNG_ERR_INVALID;
1057 goto end;
1058 }
1059 ret = lttng_dynamic_buffer_append(&payload->buffer,
1060 location_function->function_name,
1061 location_function_comm.function_name_len);
1062 if (ret) {
1063 ret = -LTTNG_ERR_INVALID;
1064 goto end;
1065 }
1066 ret = lttng_dynamic_buffer_append(&payload->buffer,
1067 location_function->binary_path,
1068 location_function_comm.binary_path_len);
1069 if (ret) {
1070 ret = -LTTNG_ERR_INVALID;
1071 goto end;
1072 }
1073 ret = lttng_payload_push_fd_handle(
1074 payload, location_function->binary_fd_handle);
1075 if (ret) {
1076 ret = -LTTNG_ERR_INVALID;
1077 goto end;
1078 }
1079 }
1080 ret = sizeof(location_function_comm) +
1081 location_function_comm.function_name_len +
1082 location_function_comm.binary_path_len;
1083 end:
1084 return ret;
1085 }
1086
1087 static
1088 int lttng_userspace_probe_location_tracepoint_serialize(
1089 const struct lttng_userspace_probe_location *location,
1090 struct lttng_payload *payload)
1091 {
1092 int ret;
1093 size_t probe_name_len, provider_name_len, binary_path_len;
1094 struct lttng_userspace_probe_location_tracepoint *location_tracepoint;
1095 struct lttng_userspace_probe_location_tracepoint_comm location_tracepoint_comm;
1096
1097 LTTNG_ASSERT(location);
1098 LTTNG_ASSERT(lttng_userspace_probe_location_get_type(location) ==
1099 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1100
1101 location_tracepoint = container_of(location,
1102 struct lttng_userspace_probe_location_tracepoint,
1103 parent);
1104 if (!location_tracepoint->probe_name ||
1105 !location_tracepoint->provider_name ||
1106 !location_tracepoint->binary_path) {
1107 ret = -LTTNG_ERR_INVALID;
1108 goto end;
1109 }
1110
1111 if (payload && !location_tracepoint->binary_fd_handle) {
1112 ret = -LTTNG_ERR_INVALID;
1113 goto end;
1114 }
1115
1116 probe_name_len = strlen(location_tracepoint->probe_name);
1117 if (probe_name_len == 0) {
1118 ret = -LTTNG_ERR_INVALID;
1119 goto end;
1120 }
1121
1122 provider_name_len = strlen(location_tracepoint->provider_name);
1123 if (provider_name_len == 0) {
1124 ret = -LTTNG_ERR_INVALID;
1125 goto end;
1126 }
1127
1128 binary_path_len = strlen(location_tracepoint->binary_path);
1129 if (binary_path_len == 0) {
1130 ret = -LTTNG_ERR_INVALID;
1131 goto end;
1132 }
1133
1134 location_tracepoint_comm.probe_name_len = probe_name_len + 1;
1135 location_tracepoint_comm.provider_name_len = provider_name_len + 1;
1136 location_tracepoint_comm.binary_path_len = binary_path_len + 1;
1137
1138 if (payload) {
1139 ret = lttng_dynamic_buffer_append(&payload->buffer,
1140 &location_tracepoint_comm,
1141 sizeof(location_tracepoint_comm));
1142 if (ret) {
1143 ret = -LTTNG_ERR_INVALID;
1144 goto end;
1145 }
1146 ret = lttng_dynamic_buffer_append(&payload->buffer,
1147 location_tracepoint->probe_name,
1148 location_tracepoint_comm.probe_name_len);
1149 if (ret) {
1150 ret = -LTTNG_ERR_INVALID;
1151 goto end;
1152 }
1153 ret = lttng_dynamic_buffer_append(&payload->buffer,
1154 location_tracepoint->provider_name,
1155 location_tracepoint_comm.provider_name_len);
1156 if (ret) {
1157 ret = -LTTNG_ERR_INVALID;
1158 goto end;
1159 }
1160 ret = lttng_dynamic_buffer_append(&payload->buffer,
1161 location_tracepoint->binary_path,
1162 location_tracepoint_comm.binary_path_len);
1163 if (ret) {
1164 ret = -LTTNG_ERR_INVALID;
1165 goto end;
1166 }
1167 ret = lttng_payload_push_fd_handle(
1168 payload, location_tracepoint->binary_fd_handle);
1169 if (ret) {
1170 ret = -LTTNG_ERR_INVALID;
1171 goto end;
1172 }
1173 }
1174
1175 ret = sizeof(location_tracepoint_comm) +
1176 location_tracepoint_comm.probe_name_len +
1177 location_tracepoint_comm.provider_name_len +
1178 location_tracepoint_comm.binary_path_len;
1179 end:
1180 return ret;
1181 }
1182
1183 int lttng_userspace_probe_location_serialize(
1184 const struct lttng_userspace_probe_location *location,
1185 struct lttng_payload *payload)
1186 {
1187 int ret, buffer_use = 0;
1188 struct lttng_userspace_probe_location_comm location_generic_comm;
1189
1190 if (!location) {
1191 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
1192 ret = -LTTNG_ERR_INVALID;
1193 goto end;
1194 }
1195
1196 memset(&location_generic_comm, 0, sizeof(location_generic_comm));
1197
1198 location_generic_comm.type = (int8_t) location->type;
1199 if (payload) {
1200 ret = lttng_dynamic_buffer_append(&payload->buffer,
1201 &location_generic_comm,
1202 sizeof(location_generic_comm));
1203 if (ret) {
1204 goto end;
1205 }
1206 }
1207 buffer_use += sizeof(location_generic_comm);
1208
1209 switch (lttng_userspace_probe_location_get_type(location)) {
1210 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1211 ret = lttng_userspace_probe_location_function_serialize(
1212 location, payload);
1213 break;
1214 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1215 ret = lttng_userspace_probe_location_tracepoint_serialize(
1216 location, payload);
1217 break;
1218 default:
1219 ERR("Unsupported probe location type");
1220 ret = -LTTNG_ERR_INVALID;
1221 goto end;
1222 }
1223 if (ret < 0) {
1224 goto end;
1225 }
1226 buffer_use += ret;
1227
1228 ret = lttng_userspace_probe_location_lookup_method_serialize(
1229 location->lookup_method, payload);
1230 if (ret < 0) {
1231 goto end;
1232 }
1233 ret += buffer_use;
1234 end:
1235 return ret;
1236 }
1237
1238 static
1239 int lttng_userspace_probe_location_function_create_from_payload(
1240 struct lttng_payload_view *view,
1241 struct lttng_userspace_probe_location **location)
1242 {
1243 struct lttng_userspace_probe_location_function_comm *location_function_comm;
1244 const char *function_name_src, *binary_path_src;
1245 char *function_name = NULL, *binary_path = NULL;
1246 int ret = 0;
1247 size_t expected_size;
1248 struct fd_handle *binary_fd_handle = lttng_payload_view_pop_fd_handle(view);
1249
1250 LTTNG_ASSERT(location);
1251
1252 if (view->buffer.size < sizeof(*location_function_comm)) {
1253 ret = -LTTNG_ERR_INVALID;
1254 goto end;
1255 }
1256
1257 location_function_comm =
1258 (typeof(location_function_comm)) view->buffer.data;
1259
1260 expected_size = sizeof(*location_function_comm) +
1261 location_function_comm->function_name_len +
1262 location_function_comm->binary_path_len;
1263
1264 if (view->buffer.size < expected_size) {
1265 ret = -LTTNG_ERR_INVALID;
1266 goto end;
1267 }
1268
1269 function_name_src = view->buffer.data + sizeof(*location_function_comm);
1270 binary_path_src = function_name_src +
1271 location_function_comm->function_name_len;
1272
1273 if (!lttng_buffer_view_contains_string(&view->buffer, function_name_src,
1274 location_function_comm->function_name_len)) {
1275 ret = -LTTNG_ERR_INVALID;
1276 goto end;
1277 }
1278
1279 if (!lttng_buffer_view_contains_string(&view->buffer, binary_path_src,
1280 location_function_comm->binary_path_len)) {
1281 ret = -LTTNG_ERR_INVALID;
1282 goto end;
1283 }
1284
1285 function_name = lttng_strndup(function_name_src, LTTNG_SYMBOL_NAME_LEN);
1286 if (!function_name) {
1287 PERROR("lttng_strndup");
1288 ret = -LTTNG_ERR_NOMEM;
1289 goto end;
1290 }
1291
1292 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1293 if (!binary_path) {
1294 PERROR("lttng_strndup");
1295 ret = -LTTNG_ERR_NOMEM;
1296 goto end;
1297 }
1298
1299 *location = lttng_userspace_probe_location_function_create_no_check(
1300 binary_path, function_name, NULL, false);
1301 if (!(*location)) {
1302 ret = -LTTNG_ERR_INVALID;
1303 goto end;
1304 }
1305
1306 ret = lttng_userspace_probe_location_function_set_binary_fd_handle(
1307 *location, binary_fd_handle);
1308 if (ret) {
1309 ret = -LTTNG_ERR_INVALID;
1310 goto end;
1311 }
1312
1313 ret = (int) expected_size;
1314 end:
1315 fd_handle_put(binary_fd_handle);
1316 free(function_name);
1317 free(binary_path);
1318 return ret;
1319 }
1320
1321 static
1322 int lttng_userspace_probe_location_tracepoint_create_from_payload(
1323 struct lttng_payload_view *view,
1324 struct lttng_userspace_probe_location **location)
1325 {
1326 struct lttng_userspace_probe_location_tracepoint_comm *location_tracepoint_comm;
1327 const char *probe_name_src, *provider_name_src, *binary_path_src;
1328 char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
1329 int ret = 0;
1330 size_t expected_size;
1331 struct fd_handle *binary_fd_handle = lttng_payload_view_pop_fd_handle(view);
1332
1333 LTTNG_ASSERT(location);
1334
1335 if (!binary_fd_handle) {
1336 ret = -LTTNG_ERR_INVALID;
1337 goto end;
1338 }
1339
1340 if (view->buffer.size < sizeof(*location_tracepoint_comm)) {
1341 ret = -LTTNG_ERR_INVALID;
1342 goto end;
1343 }
1344
1345 location_tracepoint_comm =
1346 (typeof(location_tracepoint_comm)) view->buffer.data;
1347
1348 expected_size = sizeof(*location_tracepoint_comm) +
1349 location_tracepoint_comm->probe_name_len +
1350 location_tracepoint_comm->provider_name_len +
1351 location_tracepoint_comm->binary_path_len;
1352
1353 if (view->buffer.size < expected_size) {
1354 ret = -LTTNG_ERR_INVALID;
1355 goto end;
1356 }
1357
1358 probe_name_src = view->buffer.data + sizeof(*location_tracepoint_comm);
1359 provider_name_src = probe_name_src +
1360 location_tracepoint_comm->probe_name_len;
1361 binary_path_src = provider_name_src +
1362 location_tracepoint_comm->provider_name_len;
1363
1364 if (!lttng_buffer_view_contains_string(&view->buffer, probe_name_src,
1365 location_tracepoint_comm->probe_name_len)) {
1366 ret = -LTTNG_ERR_INVALID;
1367 goto end;
1368 }
1369
1370 if (!lttng_buffer_view_contains_string(&view->buffer, provider_name_src,
1371 location_tracepoint_comm->provider_name_len)) {
1372 ret = -LTTNG_ERR_INVALID;
1373 goto end;
1374 }
1375
1376 if (!lttng_buffer_view_contains_string(&view->buffer, binary_path_src,
1377 location_tracepoint_comm->binary_path_len)) {
1378 ret = -LTTNG_ERR_INVALID;
1379 goto end;
1380 }
1381
1382 probe_name = lttng_strndup(probe_name_src, LTTNG_SYMBOL_NAME_LEN);
1383 if (!probe_name) {
1384 PERROR("Failed to allocate probe name");
1385 ret = -LTTNG_ERR_INVALID;
1386 goto end;
1387 }
1388 provider_name = lttng_strndup(provider_name_src, LTTNG_SYMBOL_NAME_LEN);
1389 if (!provider_name) {
1390 PERROR("Failed to allocate provider name");
1391 ret = -LTTNG_ERR_INVALID;
1392 goto end;
1393 }
1394
1395 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1396 if (!binary_path) {
1397 PERROR("Failed to allocate binary path");
1398 ret = -LTTNG_ERR_INVALID;
1399 goto end;
1400 }
1401
1402 *location = lttng_userspace_probe_location_tracepoint_create_no_check(
1403 binary_path, provider_name, probe_name, NULL, false);
1404 if (!(*location)) {
1405 ret = -LTTNG_ERR_INVALID;
1406 goto end;
1407 }
1408
1409 ret = lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
1410 *location, binary_fd_handle);
1411 if (ret) {
1412 ret = -LTTNG_ERR_INVALID;
1413 goto end;
1414 }
1415
1416 ret = (int) expected_size;
1417 end:
1418 fd_handle_put(binary_fd_handle);
1419 free(probe_name);
1420 free(provider_name);
1421 free(binary_path);
1422 return ret;
1423 }
1424
1425 static
1426 int lttng_userspace_probe_location_lookup_method_create_from_payload(
1427 struct lttng_payload_view *view,
1428 struct lttng_userspace_probe_location_lookup_method **lookup_method)
1429 {
1430 int ret;
1431 struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
1432 enum lttng_userspace_probe_location_lookup_method_type type;
1433
1434 LTTNG_ASSERT(view);
1435 LTTNG_ASSERT(lookup_method);
1436
1437 if (view->buffer.size < sizeof(*lookup_comm)) {
1438 ret = -LTTNG_ERR_INVALID;
1439 goto end;
1440 }
1441
1442 lookup_comm = (typeof(lookup_comm)) view->buffer.data;
1443 type = (enum lttng_userspace_probe_location_lookup_method_type)
1444 lookup_comm->type;
1445 switch (type) {
1446 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
1447 *lookup_method = NULL;
1448 break;
1449 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
1450 *lookup_method =
1451 lttng_userspace_probe_location_lookup_method_function_elf_create();
1452 if (!(*lookup_method)) {
1453 ret = -LTTNG_ERR_INVALID;
1454 goto end;
1455 }
1456 break;
1457 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
1458 *lookup_method =
1459 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1460 if (!(*lookup_method)) {
1461 ret = -LTTNG_ERR_INVALID;
1462 goto end;
1463 }
1464 break;
1465 default:
1466 ret = -LTTNG_ERR_INVALID;
1467 goto end;
1468 }
1469
1470 ret = sizeof(*lookup_comm);
1471 end:
1472 return ret;
1473 }
1474
1475 int lttng_userspace_probe_location_create_from_payload(
1476 struct lttng_payload_view *view,
1477 struct lttng_userspace_probe_location **location)
1478 {
1479 struct lttng_userspace_probe_location_lookup_method *lookup_method;
1480 enum lttng_userspace_probe_location_type type;
1481 int consumed = 0;
1482 int ret;
1483 struct lttng_userspace_probe_location_comm *probe_location_comm;
1484 struct lttng_payload_view probe_location_comm_view =
1485 lttng_payload_view_from_view(
1486 view, 0, sizeof(*probe_location_comm));
1487
1488 LTTNG_ASSERT(view);
1489 LTTNG_ASSERT(location);
1490
1491 lookup_method = NULL;
1492
1493 if (!lttng_payload_view_is_valid(&probe_location_comm_view)) {
1494 ret = -LTTNG_ERR_INVALID;
1495 goto end;
1496 }
1497
1498 probe_location_comm = (typeof(probe_location_comm)) probe_location_comm_view.buffer.data;
1499 type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
1500 consumed += sizeof(*probe_location_comm);
1501
1502 switch (type) {
1503 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1504 {
1505 struct lttng_payload_view location_view =
1506 lttng_payload_view_from_view(
1507 view, consumed, -1);
1508
1509 ret = lttng_userspace_probe_location_function_create_from_payload(
1510 &location_view, location);
1511 if (ret < 0) {
1512 goto end;
1513 }
1514 break;
1515 }
1516 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1517 {
1518 struct lttng_payload_view location_view =
1519 lttng_payload_view_from_view(view, consumed, -1);
1520
1521 ret = lttng_userspace_probe_location_tracepoint_create_from_payload(
1522 &location_view, location);
1523 if (ret < 0) {
1524 goto end;
1525 }
1526 break;
1527 }
1528 default:
1529 ret = -LTTNG_ERR_INVALID;
1530 goto end;
1531 }
1532
1533 consumed += ret;
1534 if (view->buffer.size <= consumed) {
1535 ret = -LTTNG_ERR_INVALID;
1536 goto end;
1537 }
1538
1539 {
1540 struct lttng_payload_view lookup_method_view =
1541 lttng_payload_view_from_view(
1542 view, consumed, -1);
1543
1544 ret = lttng_userspace_probe_location_lookup_method_create_from_payload(
1545 &lookup_method_view, &lookup_method);
1546 }
1547 if (ret < 0) {
1548 ret = -LTTNG_ERR_INVALID;
1549 goto end;
1550 }
1551
1552 LTTNG_ASSERT(lookup_method);
1553 (*location)->lookup_method = lookup_method;
1554 lookup_method = NULL;
1555 ret += consumed;
1556 end:
1557 return ret;
1558 }
1559
1560 static
1561 int lttng_userspace_probe_location_function_set_binary_fd_handle(
1562 struct lttng_userspace_probe_location *location,
1563 struct fd_handle *binary_fd)
1564 {
1565 int ret = 0;
1566 struct lttng_userspace_probe_location_function *function_location;
1567
1568 LTTNG_ASSERT(location);
1569 LTTNG_ASSERT(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1570
1571 function_location = container_of(location,
1572 struct lttng_userspace_probe_location_function, parent);
1573 fd_handle_put(function_location->binary_fd_handle);
1574 fd_handle_get(binary_fd);
1575 function_location->binary_fd_handle = binary_fd;
1576 return ret;
1577 }
1578
1579 static
1580 int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
1581 struct lttng_userspace_probe_location *location,
1582 struct fd_handle *binary_fd)
1583 {
1584 int ret = 0;
1585 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
1586
1587 LTTNG_ASSERT(location);
1588 LTTNG_ASSERT(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1589
1590 tracepoint_location = container_of(location,
1591 struct lttng_userspace_probe_location_tracepoint, parent);
1592 fd_handle_put(tracepoint_location->binary_fd_handle);
1593 fd_handle_get(binary_fd);
1594 tracepoint_location->binary_fd_handle = binary_fd;
1595 return ret;
1596 }
1597
1598 static
1599 int lttng_userspace_probe_location_function_flatten(
1600 const struct lttng_userspace_probe_location *location,
1601 struct lttng_dynamic_buffer *buffer)
1602 {
1603 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method;
1604 struct lttng_userspace_probe_location_function *probe_function;
1605 struct lttng_userspace_probe_location_function flat_probe;
1606 size_t function_name_len, binary_path_len;
1607 size_t padding_needed = 0;
1608 char *flat_probe_start;
1609 int storage_needed = 0;
1610 int ret;
1611
1612 LTTNG_ASSERT(location);
1613
1614 if (location->lookup_method && location->lookup_method->type !=
1615 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF) {
1616 ret = -LTTNG_ERR_INVALID;
1617 goto end;
1618 }
1619
1620 probe_function = container_of(location,
1621 struct lttng_userspace_probe_location_function,
1622 parent);
1623 LTTNG_ASSERT(probe_function->function_name);
1624 LTTNG_ASSERT(probe_function->binary_path);
1625
1626 storage_needed +=
1627 sizeof(struct lttng_userspace_probe_location_function);
1628 function_name_len = strlen(probe_function->function_name) + 1;
1629 binary_path_len = strlen(probe_function->binary_path) + 1;
1630 storage_needed += function_name_len + binary_path_len;
1631
1632 /*
1633 * The lookup method is aligned to 64-bit within the buffer.
1634 * This is needed even if there is no lookup method since
1635 * the next structure in the buffer probably needs to be
1636 * aligned too (depending on the arch).
1637 */
1638 padding_needed = lttng_align_ceil(storage_needed, sizeof(uint64_t)) - storage_needed;
1639 storage_needed += padding_needed;
1640
1641 if (location->lookup_method) {
1642 /* NOTE: elf look-up method is assumed here. */
1643 storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1644 }
1645
1646 if (!buffer) {
1647 ret = storage_needed;
1648 goto end;
1649 }
1650
1651 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1652 ret = lttng_dynamic_buffer_set_capacity(buffer,
1653 buffer->size + storage_needed);
1654 if (ret) {
1655 goto end;
1656 }
1657 }
1658
1659 memset(&flat_probe, 0, sizeof(flat_probe));
1660
1661 flat_probe_start = buffer->data + buffer->size;
1662 flat_probe.parent.type = location->type;
1663 /*
1664 * The lookup method, if present, is the last element in the flat
1665 * representation of the probe.
1666 */
1667 if (location->lookup_method) {
1668 flat_probe.parent.lookup_method =
1669 (struct lttng_userspace_probe_location_lookup_method *)
1670 (flat_probe_start + sizeof(flat_probe) +
1671 function_name_len + binary_path_len + padding_needed);
1672 } else {
1673 flat_probe.parent.lookup_method = NULL;
1674 }
1675
1676 flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
1677 flat_probe.binary_path = flat_probe.function_name + function_name_len;
1678 flat_probe.binary_fd_handle = NULL;
1679 ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
1680 sizeof(flat_probe));
1681 if (ret) {
1682 goto end;
1683 }
1684
1685 ret = lttng_dynamic_buffer_append(buffer,
1686 probe_function->function_name, function_name_len);
1687 if (ret) {
1688 goto end;
1689 }
1690 ret = lttng_dynamic_buffer_append(buffer,
1691 probe_function->binary_path, binary_path_len);
1692 if (ret) {
1693 goto end;
1694 }
1695
1696 /* Insert padding before the lookup method. */
1697 ret = lttng_dynamic_buffer_set_size(buffer,
1698 buffer->size + padding_needed);
1699 if (ret) {
1700 goto end;
1701 }
1702
1703 if (!location->lookup_method) {
1704 /* Not an error, the default method is used. */
1705 ret = storage_needed;
1706 goto end;
1707 }
1708
1709 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1710 flat_lookup_method.parent.type =
1711 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
1712 ret = lttng_dynamic_buffer_append(buffer,
1713 &flat_lookup_method, sizeof(flat_lookup_method));
1714 if (ret) {
1715 goto end;
1716 }
1717 ret = storage_needed;
1718 end:
1719 return ret;
1720 }
1721
1722 static
1723 int lttng_userspace_probe_location_tracepoint_flatten(
1724 const struct lttng_userspace_probe_location *location,
1725 struct lttng_dynamic_buffer *buffer)
1726 {
1727 struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method;
1728 struct lttng_userspace_probe_location_tracepoint *probe_tracepoint;
1729 struct lttng_userspace_probe_location_tracepoint flat_probe;
1730 size_t probe_name_len, provider_name_len, binary_path_len;
1731 size_t padding_needed = 0;
1732 int storage_needed = 0;
1733 char *flat_probe_start;
1734 int ret = 0;
1735
1736 LTTNG_ASSERT(location);
1737
1738 /* Only SDT tracepoints are supported at the moment */
1739 if (location->lookup_method && location->lookup_method->type !=
1740 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT) {
1741 ret = -LTTNG_ERR_INVALID;
1742 goto end;
1743 }
1744 probe_tracepoint = container_of(location,
1745 struct lttng_userspace_probe_location_tracepoint,
1746 parent);
1747 LTTNG_ASSERT(probe_tracepoint->probe_name);
1748 LTTNG_ASSERT(probe_tracepoint->provider_name);
1749 LTTNG_ASSERT(probe_tracepoint->binary_path);
1750
1751 /* Compute the storage space needed to flatten the probe location */
1752 storage_needed += sizeof(struct lttng_userspace_probe_location_tracepoint);
1753
1754 probe_name_len = strlen(probe_tracepoint->probe_name) + 1;
1755 provider_name_len = strlen(probe_tracepoint->provider_name) + 1;
1756 binary_path_len = strlen(probe_tracepoint->binary_path) + 1;
1757
1758 storage_needed += probe_name_len + provider_name_len + binary_path_len;
1759
1760 /*
1761 * The lookup method is aligned to 64-bit within the buffer.
1762 * This is needed even if there is no lookup method since
1763 * the next structure in the buffer probably needs to be
1764 * aligned too (depending on the arch).
1765 */
1766 padding_needed = lttng_align_ceil(storage_needed, sizeof(uint64_t)) - storage_needed;
1767 storage_needed += padding_needed;
1768
1769 if (location->lookup_method) {
1770 /* NOTE: elf look-up method is assumed here. */
1771 storage_needed +=
1772 sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1773 }
1774
1775 /*
1776 * If the caller set buffer to NULL, return the size of the needed buffer.
1777 */
1778 if (!buffer) {
1779 ret = storage_needed;
1780 goto end;
1781 }
1782
1783 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1784 ret = lttng_dynamic_buffer_set_capacity(buffer,
1785 buffer->size + storage_needed);
1786 if (ret) {
1787 goto end;
1788 }
1789 }
1790
1791 memset(&flat_probe, 0, sizeof(flat_probe));
1792
1793 flat_probe_start = buffer->data + buffer->size;
1794 flat_probe.parent.type = location->type;
1795
1796 /*
1797 * The lookup method, if present, is the last element in the flat
1798 * representation of the probe.
1799 */
1800 if (location->lookup_method) {
1801 flat_probe.parent.lookup_method =
1802 (struct lttng_userspace_probe_location_lookup_method *)
1803 (flat_probe_start + sizeof(flat_probe) +
1804 probe_name_len + provider_name_len +
1805 binary_path_len + padding_needed);
1806 } else {
1807 flat_probe.parent.lookup_method = NULL;
1808 }
1809
1810 flat_probe.probe_name = flat_probe_start + sizeof(flat_probe);
1811 flat_probe.provider_name = flat_probe.probe_name + probe_name_len;
1812 flat_probe.binary_path = flat_probe.provider_name + provider_name_len;
1813 flat_probe.binary_fd_handle = NULL;
1814 ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe));
1815 if (ret) {
1816 goto end;
1817 }
1818
1819 /* Append all the fields to the buffer */
1820 ret = lttng_dynamic_buffer_append(buffer,
1821 probe_tracepoint->probe_name, probe_name_len);
1822 if (ret) {
1823 goto end;
1824 }
1825 ret = lttng_dynamic_buffer_append(buffer,
1826 probe_tracepoint->provider_name, provider_name_len);
1827 if (ret) {
1828 goto end;
1829 }
1830 ret = lttng_dynamic_buffer_append(buffer,
1831 probe_tracepoint->binary_path, binary_path_len);
1832 if (ret) {
1833 goto end;
1834 }
1835
1836 /* Insert padding before the lookup method. */
1837 ret = lttng_dynamic_buffer_set_size(buffer, buffer->size + padding_needed);
1838 if (ret) {
1839 goto end;
1840 }
1841
1842 if (!location->lookup_method) {
1843 /* Not an error, the default method is used. */
1844 ret = storage_needed;
1845 goto end;
1846 }
1847
1848 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1849
1850 flat_lookup_method.parent.type =
1851 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
1852 ret = lttng_dynamic_buffer_append(buffer,
1853 &flat_lookup_method, sizeof(flat_lookup_method));
1854 if (ret) {
1855 goto end;
1856 }
1857 ret = storage_needed;
1858 end:
1859 return ret;
1860 }
1861
1862 int lttng_userspace_probe_location_flatten(
1863 const struct lttng_userspace_probe_location *location,
1864 struct lttng_dynamic_buffer *buffer)
1865 {
1866 int ret;
1867 if (!location) {
1868 ret = -LTTNG_ERR_INVALID;
1869 goto end;
1870 }
1871
1872 /* Only types currently supported. */
1873 switch (location->type) {
1874 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1875 ret = lttng_userspace_probe_location_function_flatten(location, buffer);
1876 break;
1877 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1878 ret = lttng_userspace_probe_location_tracepoint_flatten(location, buffer);
1879 break;
1880 default:
1881 ret = -LTTNG_ERR_INVALID;
1882 goto end;
1883 }
1884
1885 end:
1886 return ret;
1887 }
1888
1889 struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
1890 const struct lttng_userspace_probe_location *location)
1891 {
1892 struct lttng_userspace_probe_location *new_location = NULL;
1893 enum lttng_userspace_probe_location_type type;
1894
1895 if (!location) {
1896 goto err;
1897 }
1898
1899 type = lttng_userspace_probe_location_get_type(location);
1900 switch (type) {
1901 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1902 new_location =
1903 lttng_userspace_probe_location_function_copy(location);
1904 if (!new_location) {
1905 goto err;
1906 }
1907 break;
1908 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1909 new_location =
1910 lttng_userspace_probe_location_tracepoint_copy(location);
1911 if (!new_location) {
1912 goto err;
1913 }
1914 break;
1915 default:
1916 new_location = NULL;
1917 goto err;
1918 }
1919 err:
1920 return new_location;
1921 }
1922
1923 bool lttng_userspace_probe_location_lookup_method_is_equal(
1924 const struct lttng_userspace_probe_location_lookup_method *a,
1925 const struct lttng_userspace_probe_location_lookup_method *b)
1926 {
1927 bool is_equal = false;
1928
1929 if (!a || !b) {
1930 goto end;
1931 }
1932
1933 if (a == b) {
1934 is_equal = true;
1935 goto end;
1936 }
1937
1938 if (a->type != b->type) {
1939 goto end;
1940 }
1941
1942 is_equal = true;
1943 end:
1944 return is_equal;
1945 }
1946
1947 bool lttng_userspace_probe_location_is_equal(
1948 const struct lttng_userspace_probe_location *a,
1949 const struct lttng_userspace_probe_location *b)
1950 {
1951 bool is_equal = false;
1952
1953 if (!a || !b) {
1954 goto end;
1955 }
1956
1957 if (a == b) {
1958 is_equal = true;
1959 goto end;
1960 }
1961
1962 if (!lttng_userspace_probe_location_lookup_method_is_equal(
1963 a->lookup_method, b->lookup_method)) {
1964 goto end;
1965 }
1966
1967 if (a->type != b->type) {
1968 goto end;
1969 }
1970
1971 is_equal = a->equal ? a->equal(a, b) : true;
1972 end:
1973 return is_equal;
1974 }
1975
1976 unsigned long lttng_userspace_probe_location_hash(
1977 const struct lttng_userspace_probe_location *location)
1978 {
1979 return location->hash(location);
1980 }
1981
1982 enum lttng_error_code lttng_userspace_probe_location_mi_serialize(
1983 const struct lttng_userspace_probe_location *location,
1984 struct mi_writer *writer)
1985 {
1986 typedef enum lttng_error_code (*mi_fp)(
1987 const struct lttng_userspace_probe_location *,
1988 struct mi_writer *);
1989
1990 int ret;
1991 enum lttng_error_code ret_code;
1992 mi_fp mi_function = NULL;
1993
1994 LTTNG_ASSERT(location);
1995 LTTNG_ASSERT(writer);
1996
1997 switch (lttng_userspace_probe_location_get_type(location)) {
1998 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1999 mi_function = lttng_userspace_probe_location_function_mi_serialize;
2000 break;
2001 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
2002 mi_function = lttng_userspace_probe_location_tracepoint_mi_serialize;
2003 break;
2004 default:
2005 abort();
2006 break;
2007 }
2008
2009 /* Open userspace probe location element. */
2010 ret = mi_lttng_writer_open_element(
2011 writer, mi_lttng_element_userspace_probe_location);
2012 if (ret) {
2013 goto mi_error;
2014 }
2015
2016 /* Underlying user space probe location. */
2017 ret_code = mi_function(location, writer);
2018 if (ret_code != LTTNG_OK) {
2019 goto end;
2020 }
2021
2022 /* Close userspace probe location element. */
2023 ret = mi_lttng_writer_close_element(writer);
2024 if (ret) {
2025 goto mi_error;
2026 }
2027
2028 ret_code = LTTNG_OK;
2029 goto end;
2030
2031 mi_error:
2032 ret_code = LTTNG_ERR_MI_IO_FAIL;
2033 end:
2034 return ret_code;
2035 }
2036
2037 enum lttng_error_code lttng_userspace_probe_location_lookup_method_mi_serialize(
2038 const struct lttng_userspace_probe_location_lookup_method
2039 *method,
2040 struct mi_writer *writer)
2041 {
2042 int ret;
2043 enum lttng_error_code ret_code;
2044 const char *type_element_str;
2045
2046 LTTNG_ASSERT(method);
2047 LTTNG_ASSERT(writer);
2048
2049 switch (lttng_userspace_probe_location_lookup_method_get_type(method)) {
2050 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
2051 type_element_str =
2052 mi_lttng_element_userspace_probe_location_lookup_method_function_default;
2053 break;
2054 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
2055 type_element_str =
2056 mi_lttng_element_userspace_probe_location_lookup_method_function_elf;
2057 break;
2058 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
2059 type_element_str =
2060 mi_lttng_element_userspace_probe_location_lookup_method_tracepoint_sdt;
2061 break;
2062 default:
2063 abort();
2064 break;
2065 }
2066
2067 /* Open userspace probe location lookup method element. */
2068 ret = mi_lttng_writer_open_element(writer,
2069 mi_lttng_element_userspace_probe_location_lookup_method);
2070 if (ret) {
2071 goto mi_error;
2072 }
2073
2074 /* User space probe location lookup method empty element. */
2075 ret = mi_lttng_writer_open_element(writer, type_element_str);
2076 if (ret) {
2077 goto mi_error;
2078 }
2079
2080 /* Close userspace probe location lookup method element. */
2081 ret = mi_lttng_close_multi_element(writer, 2);
2082 if (ret) {
2083 goto mi_error;
2084 }
2085
2086 ret_code = LTTNG_OK;
2087 goto end;
2088
2089 mi_error:
2090 ret_code = LTTNG_ERR_MI_IO_FAIL;
2091 end:
2092 return ret_code;
2093 }
2094
2095 static enum lttng_error_code lttng_userspace_probe_location_tracepoint_mi_serialize(
2096 const struct lttng_userspace_probe_location *location,
2097 struct mi_writer *writer)
2098 {
2099 int ret;
2100 enum lttng_error_code ret_code;
2101 const char *probe_name = NULL;
2102 const char *provider_name = NULL;
2103 const char *binary_path = NULL;
2104 const struct lttng_userspace_probe_location_lookup_method
2105 *lookup_method = NULL;
2106
2107 LTTNG_ASSERT(location);
2108 LTTNG_ASSERT(writer);
2109
2110 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(
2111 location);
2112 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(
2113 location);
2114 binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(
2115 location);
2116 lookup_method = lttng_userspace_probe_location_tracepoint_get_lookup_method(
2117 location);
2118
2119 /* Open userspace probe location tracepoint element. */
2120 ret = mi_lttng_writer_open_element(writer,
2121 mi_lttng_element_userspace_probe_location_tracepoint);
2122 if (ret) {
2123 goto mi_error;
2124 }
2125
2126 /* Probe name. */
2127 ret = mi_lttng_writer_write_element_string(writer,
2128 mi_lttng_element_userspace_probe_location_tracepoint_probe_name,
2129 probe_name);
2130 if (ret) {
2131 goto mi_error;
2132 }
2133
2134 /* Provider name. */
2135 ret = mi_lttng_writer_write_element_string(writer,
2136 mi_lttng_element_userspace_probe_location_tracepoint_provider_name,
2137 provider_name);
2138 if (ret) {
2139 goto mi_error;
2140 }
2141
2142 /* Binary path. */
2143 ret = mi_lttng_writer_write_element_string(writer,
2144 mi_lttng_element_userspace_probe_location_binary_path,
2145 binary_path);
2146 if (ret) {
2147 goto mi_error;
2148 }
2149
2150 /* The lookup method. */
2151 ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize(
2152 lookup_method, writer);
2153 if (ret_code != LTTNG_OK) {
2154 goto end;
2155 }
2156
2157 /* Close userspace probe location tracepoint. */
2158 ret = mi_lttng_writer_close_element(writer);
2159 if (ret) {
2160 goto mi_error;
2161 }
2162
2163 ret_code = LTTNG_OK;
2164 goto end;
2165
2166 mi_error:
2167 ret_code = LTTNG_ERR_MI_IO_FAIL;
2168 end:
2169 return ret_code;
2170 }
2171
2172 static enum lttng_error_code lttng_userspace_probe_location_function_mi_serialize(
2173 const struct lttng_userspace_probe_location *location,
2174 struct mi_writer *writer)
2175 {
2176 int ret;
2177 enum lttng_error_code ret_code;
2178 const char *function_name = NULL;
2179 const char *binary_path = NULL;
2180 const char *instrumentation_type_str = NULL;
2181 enum lttng_userspace_probe_location_function_instrumentation_type
2182 instrumentation_type;
2183 const struct lttng_userspace_probe_location_lookup_method
2184 *lookup_method = NULL;
2185
2186 LTTNG_ASSERT(location);
2187 LTTNG_ASSERT(writer);
2188
2189 function_name = lttng_userspace_probe_location_function_get_function_name(
2190 location);
2191 binary_path = lttng_userspace_probe_location_function_get_binary_path(
2192 location);
2193 instrumentation_type =
2194 lttng_userspace_probe_location_function_get_instrumentation_type(
2195 location);
2196 lookup_method = lttng_userspace_probe_location_function_get_lookup_method(
2197 location);
2198
2199 switch (instrumentation_type) {
2200 case LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY:
2201 instrumentation_type_str =
2202 mi_lttng_userspace_probe_location_function_instrumentation_type_entry;
2203 break;
2204 default:
2205 abort();
2206 break;
2207 }
2208
2209 /* Open userspace probe location function element. */
2210 ret = mi_lttng_writer_open_element(writer,
2211 mi_lttng_element_userspace_probe_location_function);
2212 if (ret) {
2213 goto mi_error;
2214 }
2215
2216 /* Function name. */
2217 ret = mi_lttng_writer_write_element_string(writer,
2218 mi_lttng_element_userspace_probe_location_function_name,
2219 function_name);
2220 if (ret) {
2221 goto mi_error;
2222 }
2223
2224 /* Binary path. */
2225 ret = mi_lttng_writer_write_element_string(writer,
2226 mi_lttng_element_userspace_probe_location_binary_path,
2227 binary_path);
2228 if (ret) {
2229 goto mi_error;
2230 }
2231
2232 /* Instrumentation type. */
2233 ret = mi_lttng_writer_write_element_string(writer,
2234 mi_lttng_element_userspace_probe_location_function_instrumentation_type,
2235 instrumentation_type_str);
2236 if (ret) {
2237 goto mi_error;
2238 }
2239
2240 /* The lookup method. */
2241 ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize(
2242 lookup_method, writer);
2243 if (ret_code != LTTNG_OK) {
2244 goto end;
2245 }
2246
2247 /* Close userspace probe location function element. */
2248 ret = mi_lttng_writer_close_element(writer);
2249 if (ret) {
2250 goto mi_error;
2251 }
2252
2253 ret_code = LTTNG_OK;
2254 goto end;
2255
2256 mi_error:
2257 ret_code = LTTNG_ERR_MI_IO_FAIL;
2258 end:
2259 return ret_code;
2260 }
This page took 0.075696 seconds and 4 git commands to generate.