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