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