Fix: userspace-probe: truncating binary path for SDT
[lttng-tools.git] / src / common / userspace-probe.c
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.h>
10 #include <common/error.h>
11 #include <common/hashtable/hashtable.h>
12 #include <common/hashtable/utils.h>
13 #include <common/macros.h>
14 #include <common/mi-lttng.h>
15 #include <common/payload-view.h>
16 #include <common/payload.h>
17 #include <fcntl.h>
18 #include <lttng/constant.h>
19 #include <lttng/userspace-probe-internal.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <sys/unistd.h>
23
24 static
25 int lttng_userspace_probe_location_function_set_binary_fd_handle(
26 struct lttng_userspace_probe_location *location,
27 struct fd_handle *binary_fd_handle);
28
29 static
30 int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
31 struct lttng_userspace_probe_location *location,
32 struct fd_handle *binary_fd_handle);
33
34 static
35 enum lttng_error_code lttng_userspace_probe_location_lookup_method_mi_serialize(
36 const struct lttng_userspace_probe_location_lookup_method
37 *method,
38 struct mi_writer *writer);
39
40 static
41 enum lttng_error_code lttng_userspace_probe_location_tracepoint_mi_serialize(
42 const struct lttng_userspace_probe_location *location,
43 struct mi_writer *writer);
44
45 static
46 enum lttng_error_code lttng_userspace_probe_location_function_mi_serialize(
47 const struct lttng_userspace_probe_location *location,
48 struct mi_writer *writer);
49
50 enum lttng_userspace_probe_location_lookup_method_type
51 lttng_userspace_probe_location_lookup_method_get_type(
52 const struct lttng_userspace_probe_location_lookup_method *lookup_method)
53 {
54 return lookup_method ? lookup_method->type :
55 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_UNKNOWN;
56 }
57
58 void lttng_userspace_probe_location_lookup_method_destroy(
59 struct lttng_userspace_probe_location_lookup_method *lookup_method)
60 {
61 if (!lookup_method){
62 return;
63 }
64
65 free(lookup_method);
66 }
67
68 struct lttng_userspace_probe_location_lookup_method *
69 lttng_userspace_probe_location_lookup_method_function_elf_create(void)
70 {
71 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
72 struct lttng_userspace_probe_location_lookup_method_elf *elf_method;
73
74 elf_method = zmalloc(sizeof(*elf_method));
75 if (!elf_method) {
76 PERROR("zmalloc");
77 goto end;
78 }
79
80 ret = &elf_method->parent;
81 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
82 end:
83 return ret;
84 }
85
86 struct lttng_userspace_probe_location_lookup_method *
87 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create(void)
88 {
89 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
90 struct lttng_userspace_probe_location_lookup_method_sdt *sdt_method;
91
92 sdt_method = zmalloc(sizeof(*sdt_method));
93 if (!sdt_method) {
94 PERROR("zmalloc");
95 goto end;
96 }
97
98 ret = &sdt_method->parent;
99 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
100 end:
101 return ret;
102 }
103
104 enum lttng_userspace_probe_location_type lttng_userspace_probe_location_get_type(
105 const struct lttng_userspace_probe_location *location)
106 {
107 return location ? location->type :
108 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN;
109 }
110
111 static
112 void lttng_userspace_probe_location_function_destroy(
113 struct lttng_userspace_probe_location *location)
114 {
115 struct lttng_userspace_probe_location_function *location_function = NULL;
116
117 LTTNG_ASSERT(location);
118
119 location_function = container_of(location,
120 struct lttng_userspace_probe_location_function, parent);
121
122 LTTNG_ASSERT(location_function);
123
124 free(location_function->function_name);
125 free(location_function->binary_path);
126 fd_handle_put(location_function->binary_fd_handle);
127 free(location);
128 }
129
130 static
131 void lttng_userspace_probe_location_tracepoint_destroy(
132 struct lttng_userspace_probe_location *location)
133 {
134 struct lttng_userspace_probe_location_tracepoint *location_tracepoint = NULL;
135
136 LTTNG_ASSERT(location);
137
138 location_tracepoint = container_of(location,
139 struct lttng_userspace_probe_location_tracepoint,
140 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 container_of(location, typeof(*function_location),
228 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 = container_of(_a, struct lttng_userspace_probe_location_function,
247 parent);
248 b = container_of(_b, struct lttng_userspace_probe_location_function,
249 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(sizeof(*location));
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 =
353 container_of(location, typeof(*tp_location), 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 = container_of(_a, struct lttng_userspace_probe_location_tracepoint,
373 parent);
374 b = container_of(_b, struct lttng_userspace_probe_location_tracepoint,
375 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(sizeof(*location));
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(sizeof(*elf_method));
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(sizeof(*sdt_method));
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 = container_of(
607 location, typeof(*function_location), 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 = container_of(
681 location, typeof(*tracepoint_location), 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 = container_of(location,
759 struct lttng_userspace_probe_location_function,
760 parent);
761 ret = function_location->binary_path;
762 end:
763 return ret;
764 }
765
766 const char *lttng_userspace_probe_location_tracepoint_get_binary_path(
767 const struct lttng_userspace_probe_location *location)
768 {
769 const char *ret = NULL;
770 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
771
772 if (!location || lttng_userspace_probe_location_get_type(location) !=
773 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
774 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
775 goto end;
776 }
777
778 tracepoint_location = container_of(location,
779 struct lttng_userspace_probe_location_tracepoint,
780 parent);
781 ret = tracepoint_location->binary_path;
782 end:
783 return ret;
784 }
785
786 const char *lttng_userspace_probe_location_function_get_function_name(
787 const struct lttng_userspace_probe_location *location)
788 {
789 const char *ret = NULL;
790 struct lttng_userspace_probe_location_function *function_location;
791
792 if (!location || lttng_userspace_probe_location_get_type(location) !=
793 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
794 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
795 goto end;
796 }
797
798 function_location = container_of(location,
799 struct lttng_userspace_probe_location_function, parent);
800 ret = function_location->function_name;
801 end:
802 return ret;
803 }
804
805 const char *lttng_userspace_probe_location_tracepoint_get_probe_name(
806 const struct lttng_userspace_probe_location *location)
807 {
808 const char *ret = NULL;
809 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
810
811 if (!location || lttng_userspace_probe_location_get_type(location) !=
812 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
813 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
814 goto end;
815 }
816
817 tracepoint_location = container_of(location,
818 struct lttng_userspace_probe_location_tracepoint, parent);
819 ret = tracepoint_location->probe_name;
820 end:
821 return ret;
822 }
823
824 const char *lttng_userspace_probe_location_tracepoint_get_provider_name(
825 const struct lttng_userspace_probe_location *location)
826 {
827 const char *ret = NULL;
828 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
829
830 if (!location || lttng_userspace_probe_location_get_type(location) !=
831 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
832 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
833 goto end;
834 }
835
836 tracepoint_location = container_of(location,
837 struct lttng_userspace_probe_location_tracepoint, parent);
838 ret = tracepoint_location->provider_name;
839 end:
840 return ret;
841 }
842
843 int lttng_userspace_probe_location_function_get_binary_fd(
844 const struct lttng_userspace_probe_location *location)
845 {
846 int ret = -1;
847 struct lttng_userspace_probe_location_function *function_location;
848
849 if (!location || lttng_userspace_probe_location_get_type(location) !=
850 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
851 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
852 goto end;
853 }
854
855 function_location = container_of(location,
856 struct lttng_userspace_probe_location_function, parent);
857 ret = function_location->binary_fd_handle ?
858 fd_handle_get_fd(function_location->binary_fd_handle) : -1;
859 end:
860 return ret;
861 }
862
863 enum lttng_userspace_probe_location_function_instrumentation_type
864 lttng_userspace_probe_location_function_get_instrumentation_type(
865 const struct lttng_userspace_probe_location *location)
866 {
867 enum lttng_userspace_probe_location_function_instrumentation_type type;
868 struct lttng_userspace_probe_location_function *function_location;
869
870 if (!location || lttng_userspace_probe_location_get_type(location) !=
871 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
872 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
873 type = LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_UNKNOWN;
874 goto end;
875 }
876
877 function_location = container_of(location,
878 struct lttng_userspace_probe_location_function, parent);
879 type = function_location->instrumentation_type;
880 end:
881 return type;
882 }
883
884 enum lttng_userspace_probe_location_status
885 lttng_userspace_probe_location_function_set_instrumentation_type(
886 const struct lttng_userspace_probe_location *location,
887 enum lttng_userspace_probe_location_function_instrumentation_type instrumentation_type)
888 {
889 enum lttng_userspace_probe_location_status status =
890 LTTNG_USERSPACE_PROBE_LOCATION_STATUS_OK;
891 struct lttng_userspace_probe_location_function *function_location;
892
893 if (!location || lttng_userspace_probe_location_get_type(location) !=
894 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION ||
895 instrumentation_type !=
896 LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY) {
897 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
898 status = LTTNG_USERSPACE_PROBE_LOCATION_STATUS_INVALID;
899 goto end;
900 }
901
902 function_location = container_of(location,
903 struct lttng_userspace_probe_location_function, parent);
904 function_location->instrumentation_type = instrumentation_type;
905 end:
906 return status;
907 }
908
909 int lttng_userspace_probe_location_tracepoint_get_binary_fd(
910 const struct lttng_userspace_probe_location *location)
911 {
912 int ret = -1;
913 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
914
915 if (!location || lttng_userspace_probe_location_get_type(location) !=
916 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
917 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
918 goto end;
919 }
920
921 tracepoint_location = container_of(location,
922 struct lttng_userspace_probe_location_tracepoint, parent);
923 ret = tracepoint_location->binary_fd_handle ?
924 fd_handle_get_fd(tracepoint_location->binary_fd_handle) : -1;
925 end:
926 return ret;
927 }
928
929 static struct lttng_userspace_probe_location_lookup_method *
930 lttng_userspace_probe_location_function_get_lookup_method(
931 const struct lttng_userspace_probe_location *location)
932 {
933 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
934
935 if (!location || lttng_userspace_probe_location_get_type(location) !=
936 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
937 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
938 goto end;
939 }
940
941 ret = location->lookup_method;
942 end:
943 return ret;
944 }
945
946 static struct lttng_userspace_probe_location_lookup_method *
947 lttng_userspace_probe_location_tracepoint_get_lookup_method(
948 const struct lttng_userspace_probe_location *location)
949 {
950 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
951
952 if (!location || lttng_userspace_probe_location_get_type(location) !=
953 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
954 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
955 goto end;
956 }
957
958 ret = location->lookup_method;
959 end:
960 return ret;
961 }
962
963 const struct lttng_userspace_probe_location_lookup_method *
964 lttng_userspace_probe_location_get_lookup_method(
965 const struct lttng_userspace_probe_location *location)
966 {
967 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
968
969 LTTNG_ASSERT(location);
970 switch (location->type) {
971 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
972 ret = lttng_userspace_probe_location_function_get_lookup_method(
973 location);
974 break;
975 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
976 ret = lttng_userspace_probe_location_tracepoint_get_lookup_method(
977 location);
978 break;
979 default:
980 ERR("Unknowned lookup method.");
981 break;
982 }
983 return ret;
984 }
985
986 static
987 int lttng_userspace_probe_location_lookup_method_serialize(
988 struct lttng_userspace_probe_location_lookup_method *method,
989 struct lttng_payload *payload)
990 {
991 int ret;
992 struct lttng_userspace_probe_location_lookup_method_comm
993 lookup_method_comm;
994
995 lookup_method_comm.type = (int8_t) (method ? method->type :
996 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT);
997 if (payload) {
998 ret = lttng_dynamic_buffer_append(&payload->buffer, &lookup_method_comm,
999 sizeof(lookup_method_comm));
1000 if (ret) {
1001 goto end;
1002 }
1003 }
1004 ret = sizeof(lookup_method_comm);
1005 end:
1006 return ret;
1007 }
1008
1009 static
1010 int lttng_userspace_probe_location_function_serialize(
1011 const struct lttng_userspace_probe_location *location,
1012 struct lttng_payload *payload)
1013 {
1014 int ret;
1015 size_t function_name_len, binary_path_len;
1016 struct lttng_userspace_probe_location_function *location_function;
1017 struct lttng_userspace_probe_location_function_comm location_function_comm;
1018
1019 LTTNG_ASSERT(location);
1020 LTTNG_ASSERT(lttng_userspace_probe_location_get_type(location) ==
1021 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1022
1023 location_function = container_of(location,
1024 struct lttng_userspace_probe_location_function,
1025 parent);
1026 if (!location_function->function_name || !location_function->binary_path) {
1027 ret = -LTTNG_ERR_INVALID;
1028 goto end;
1029 }
1030
1031 if (payload && !location_function->binary_fd_handle) {
1032 ret = -LTTNG_ERR_INVALID;
1033 goto end;
1034 }
1035
1036 function_name_len = strlen(location_function->function_name);
1037 if (function_name_len == 0) {
1038 ret = -LTTNG_ERR_INVALID;
1039 goto end;
1040 }
1041 binary_path_len = strlen(location_function->binary_path);
1042 if (binary_path_len == 0) {
1043 ret = -LTTNG_ERR_INVALID;
1044 goto end;
1045 }
1046
1047 location_function_comm.function_name_len = function_name_len + 1;
1048 location_function_comm.binary_path_len = binary_path_len + 1;
1049
1050 if (payload) {
1051 ret = lttng_dynamic_buffer_append(&payload->buffer,
1052 &location_function_comm,
1053 sizeof(location_function_comm));
1054 if (ret) {
1055 ret = -LTTNG_ERR_INVALID;
1056 goto end;
1057 }
1058 ret = lttng_dynamic_buffer_append(&payload->buffer,
1059 location_function->function_name,
1060 location_function_comm.function_name_len);
1061 if (ret) {
1062 ret = -LTTNG_ERR_INVALID;
1063 goto end;
1064 }
1065 ret = lttng_dynamic_buffer_append(&payload->buffer,
1066 location_function->binary_path,
1067 location_function_comm.binary_path_len);
1068 if (ret) {
1069 ret = -LTTNG_ERR_INVALID;
1070 goto end;
1071 }
1072 ret = lttng_payload_push_fd_handle(
1073 payload, location_function->binary_fd_handle);
1074 if (ret) {
1075 ret = -LTTNG_ERR_INVALID;
1076 goto end;
1077 }
1078 }
1079 ret = sizeof(location_function_comm) +
1080 location_function_comm.function_name_len +
1081 location_function_comm.binary_path_len;
1082 end:
1083 return ret;
1084 }
1085
1086 static
1087 int lttng_userspace_probe_location_tracepoint_serialize(
1088 const struct lttng_userspace_probe_location *location,
1089 struct lttng_payload *payload)
1090 {
1091 int ret;
1092 size_t probe_name_len, provider_name_len, binary_path_len;
1093 struct lttng_userspace_probe_location_tracepoint *location_tracepoint;
1094 struct lttng_userspace_probe_location_tracepoint_comm location_tracepoint_comm;
1095
1096 LTTNG_ASSERT(location);
1097 LTTNG_ASSERT(lttng_userspace_probe_location_get_type(location) ==
1098 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1099
1100 location_tracepoint = container_of(location,
1101 struct lttng_userspace_probe_location_tracepoint,
1102 parent);
1103 if (!location_tracepoint->probe_name ||
1104 !location_tracepoint->provider_name ||
1105 !location_tracepoint->binary_path) {
1106 ret = -LTTNG_ERR_INVALID;
1107 goto end;
1108 }
1109
1110 if (payload && !location_tracepoint->binary_fd_handle) {
1111 ret = -LTTNG_ERR_INVALID;
1112 goto end;
1113 }
1114
1115 probe_name_len = strlen(location_tracepoint->probe_name);
1116 if (probe_name_len == 0) {
1117 ret = -LTTNG_ERR_INVALID;
1118 goto end;
1119 }
1120
1121 provider_name_len = strlen(location_tracepoint->provider_name);
1122 if (provider_name_len == 0) {
1123 ret = -LTTNG_ERR_INVALID;
1124 goto end;
1125 }
1126
1127 binary_path_len = strlen(location_tracepoint->binary_path);
1128 if (binary_path_len == 0) {
1129 ret = -LTTNG_ERR_INVALID;
1130 goto end;
1131 }
1132
1133 location_tracepoint_comm.probe_name_len = probe_name_len + 1;
1134 location_tracepoint_comm.provider_name_len = provider_name_len + 1;
1135 location_tracepoint_comm.binary_path_len = binary_path_len + 1;
1136
1137 if (payload) {
1138 ret = lttng_dynamic_buffer_append(&payload->buffer,
1139 &location_tracepoint_comm,
1140 sizeof(location_tracepoint_comm));
1141 if (ret) {
1142 ret = -LTTNG_ERR_INVALID;
1143 goto end;
1144 }
1145 ret = lttng_dynamic_buffer_append(&payload->buffer,
1146 location_tracepoint->probe_name,
1147 location_tracepoint_comm.probe_name_len);
1148 if (ret) {
1149 ret = -LTTNG_ERR_INVALID;
1150 goto end;
1151 }
1152 ret = lttng_dynamic_buffer_append(&payload->buffer,
1153 location_tracepoint->provider_name,
1154 location_tracepoint_comm.provider_name_len);
1155 if (ret) {
1156 ret = -LTTNG_ERR_INVALID;
1157 goto end;
1158 }
1159 ret = lttng_dynamic_buffer_append(&payload->buffer,
1160 location_tracepoint->binary_path,
1161 location_tracepoint_comm.binary_path_len);
1162 if (ret) {
1163 ret = -LTTNG_ERR_INVALID;
1164 goto end;
1165 }
1166 ret = lttng_payload_push_fd_handle(
1167 payload, location_tracepoint->binary_fd_handle);
1168 if (ret) {
1169 ret = -LTTNG_ERR_INVALID;
1170 goto end;
1171 }
1172 }
1173
1174 ret = sizeof(location_tracepoint_comm) +
1175 location_tracepoint_comm.probe_name_len +
1176 location_tracepoint_comm.provider_name_len +
1177 location_tracepoint_comm.binary_path_len;
1178 end:
1179 return ret;
1180 }
1181
1182 LTTNG_HIDDEN
1183 int lttng_userspace_probe_location_serialize(
1184 const struct lttng_userspace_probe_location *location,
1185 struct lttng_payload *payload)
1186 {
1187 int ret, buffer_use = 0;
1188 struct lttng_userspace_probe_location_comm location_generic_comm;
1189
1190 if (!location) {
1191 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
1192 ret = -LTTNG_ERR_INVALID;
1193 goto end;
1194 }
1195
1196 memset(&location_generic_comm, 0, sizeof(location_generic_comm));
1197
1198 location_generic_comm.type = (int8_t) location->type;
1199 if (payload) {
1200 ret = lttng_dynamic_buffer_append(&payload->buffer,
1201 &location_generic_comm,
1202 sizeof(location_generic_comm));
1203 if (ret) {
1204 goto end;
1205 }
1206 }
1207 buffer_use += sizeof(location_generic_comm);
1208
1209 switch (lttng_userspace_probe_location_get_type(location)) {
1210 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1211 ret = lttng_userspace_probe_location_function_serialize(
1212 location, payload);
1213 break;
1214 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1215 ret = lttng_userspace_probe_location_tracepoint_serialize(
1216 location, payload);
1217 break;
1218 default:
1219 ERR("Unsupported probe location type");
1220 ret = -LTTNG_ERR_INVALID;
1221 goto end;
1222 }
1223 if (ret < 0) {
1224 goto end;
1225 }
1226 buffer_use += ret;
1227
1228 ret = lttng_userspace_probe_location_lookup_method_serialize(
1229 location->lookup_method, payload);
1230 if (ret < 0) {
1231 goto end;
1232 }
1233 ret += buffer_use;
1234 end:
1235 return ret;
1236 }
1237
1238 static
1239 int lttng_userspace_probe_location_function_create_from_payload(
1240 struct lttng_payload_view *view,
1241 struct lttng_userspace_probe_location **location)
1242 {
1243 struct lttng_userspace_probe_location_function_comm *location_function_comm;
1244 const char *function_name_src, *binary_path_src;
1245 char *function_name = NULL, *binary_path = NULL;
1246 int ret = 0;
1247 size_t expected_size;
1248 struct fd_handle *binary_fd_handle = lttng_payload_view_pop_fd_handle(view);
1249
1250 LTTNG_ASSERT(location);
1251
1252 if (view->buffer.size < sizeof(*location_function_comm)) {
1253 ret = -LTTNG_ERR_INVALID;
1254 goto end;
1255 }
1256
1257 location_function_comm =
1258 (typeof(location_function_comm)) view->buffer.data;
1259
1260 expected_size = sizeof(*location_function_comm) +
1261 location_function_comm->function_name_len +
1262 location_function_comm->binary_path_len;
1263
1264 if (view->buffer.size < expected_size) {
1265 ret = -LTTNG_ERR_INVALID;
1266 goto end;
1267 }
1268
1269 function_name_src = view->buffer.data + sizeof(*location_function_comm);
1270 binary_path_src = function_name_src +
1271 location_function_comm->function_name_len;
1272
1273 if (!lttng_buffer_view_contains_string(&view->buffer, function_name_src,
1274 location_function_comm->function_name_len)) {
1275 ret = -LTTNG_ERR_INVALID;
1276 goto end;
1277 }
1278
1279 if (!lttng_buffer_view_contains_string(&view->buffer, binary_path_src,
1280 location_function_comm->binary_path_len)) {
1281 ret = -LTTNG_ERR_INVALID;
1282 goto end;
1283 }
1284
1285 function_name = lttng_strndup(function_name_src, LTTNG_SYMBOL_NAME_LEN);
1286 if (!function_name) {
1287 PERROR("lttng_strndup");
1288 ret = -LTTNG_ERR_NOMEM;
1289 goto end;
1290 }
1291
1292 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1293 if (!binary_path) {
1294 PERROR("lttng_strndup");
1295 ret = -LTTNG_ERR_NOMEM;
1296 goto end;
1297 }
1298
1299 *location = lttng_userspace_probe_location_function_create_no_check(
1300 binary_path, function_name, NULL, false);
1301 if (!(*location)) {
1302 ret = -LTTNG_ERR_INVALID;
1303 goto end;
1304 }
1305
1306 ret = lttng_userspace_probe_location_function_set_binary_fd_handle(
1307 *location, binary_fd_handle);
1308 if (ret) {
1309 ret = -LTTNG_ERR_INVALID;
1310 goto end;
1311 }
1312
1313 ret = (int) expected_size;
1314 end:
1315 fd_handle_put(binary_fd_handle);
1316 free(function_name);
1317 free(binary_path);
1318 return ret;
1319 }
1320
1321 static
1322 int lttng_userspace_probe_location_tracepoint_create_from_payload(
1323 struct lttng_payload_view *view,
1324 struct lttng_userspace_probe_location **location)
1325 {
1326 struct lttng_userspace_probe_location_tracepoint_comm *location_tracepoint_comm;
1327 const char *probe_name_src, *provider_name_src, *binary_path_src;
1328 char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
1329 int ret = 0;
1330 size_t expected_size;
1331 struct fd_handle *binary_fd_handle = lttng_payload_view_pop_fd_handle(view);
1332
1333 LTTNG_ASSERT(location);
1334
1335 if (!binary_fd_handle) {
1336 ret = -LTTNG_ERR_INVALID;
1337 goto end;
1338 }
1339
1340 if (view->buffer.size < sizeof(*location_tracepoint_comm)) {
1341 ret = -LTTNG_ERR_INVALID;
1342 goto end;
1343 }
1344
1345 location_tracepoint_comm =
1346 (typeof(location_tracepoint_comm)) view->buffer.data;
1347
1348 expected_size = sizeof(*location_tracepoint_comm) +
1349 location_tracepoint_comm->probe_name_len +
1350 location_tracepoint_comm->provider_name_len +
1351 location_tracepoint_comm->binary_path_len;
1352
1353 if (view->buffer.size < expected_size) {
1354 ret = -LTTNG_ERR_INVALID;
1355 goto end;
1356 }
1357
1358 probe_name_src = view->buffer.data + sizeof(*location_tracepoint_comm);
1359 provider_name_src = probe_name_src +
1360 location_tracepoint_comm->probe_name_len;
1361 binary_path_src = provider_name_src +
1362 location_tracepoint_comm->provider_name_len;
1363
1364 if (!lttng_buffer_view_contains_string(&view->buffer, probe_name_src,
1365 location_tracepoint_comm->probe_name_len)) {
1366 ret = -LTTNG_ERR_INVALID;
1367 goto end;
1368 }
1369
1370 if (!lttng_buffer_view_contains_string(&view->buffer, provider_name_src,
1371 location_tracepoint_comm->provider_name_len)) {
1372 ret = -LTTNG_ERR_INVALID;
1373 goto end;
1374 }
1375
1376 if (!lttng_buffer_view_contains_string(&view->buffer, binary_path_src,
1377 location_tracepoint_comm->binary_path_len)) {
1378 ret = -LTTNG_ERR_INVALID;
1379 goto end;
1380 }
1381
1382 probe_name = lttng_strndup(probe_name_src, LTTNG_SYMBOL_NAME_LEN);
1383 if (!probe_name) {
1384 PERROR("lttng_strndup");
1385 goto end;
1386 }
1387 provider_name = lttng_strndup(provider_name_src, LTTNG_SYMBOL_NAME_LEN);
1388 if (!provider_name) {
1389 PERROR("lttng_strndup");
1390 goto end;
1391 }
1392
1393 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1394 if (!binary_path) {
1395 PERROR("lttng_strndup");
1396 goto end;
1397 }
1398
1399 *location = lttng_userspace_probe_location_tracepoint_create_no_check(
1400 binary_path, provider_name, probe_name, NULL, false);
1401 if (!(*location)) {
1402 ret = -LTTNG_ERR_INVALID;
1403 goto end;
1404 }
1405
1406 ret = lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
1407 *location, binary_fd_handle);
1408 if (ret) {
1409 ret = -LTTNG_ERR_INVALID;
1410 goto end;
1411 }
1412
1413 ret = (int) expected_size;
1414 end:
1415 fd_handle_put(binary_fd_handle);
1416 free(probe_name);
1417 free(provider_name);
1418 free(binary_path);
1419 return ret;
1420 }
1421
1422 static
1423 int lttng_userspace_probe_location_lookup_method_create_from_payload(
1424 struct lttng_payload_view *view,
1425 struct lttng_userspace_probe_location_lookup_method **lookup_method)
1426 {
1427 int ret;
1428 struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
1429 enum lttng_userspace_probe_location_lookup_method_type type;
1430
1431 LTTNG_ASSERT(view);
1432 LTTNG_ASSERT(lookup_method);
1433
1434 if (view->buffer.size < sizeof(*lookup_comm)) {
1435 ret = -LTTNG_ERR_INVALID;
1436 goto end;
1437 }
1438
1439 lookup_comm = (typeof(lookup_comm)) view->buffer.data;
1440 type = (enum lttng_userspace_probe_location_lookup_method_type)
1441 lookup_comm->type;
1442 switch (type) {
1443 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
1444 *lookup_method = NULL;
1445 break;
1446 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
1447 *lookup_method =
1448 lttng_userspace_probe_location_lookup_method_function_elf_create();
1449 if (!(*lookup_method)) {
1450 ret = -LTTNG_ERR_INVALID;
1451 goto end;
1452 }
1453 break;
1454 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
1455 *lookup_method =
1456 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1457 if (!(*lookup_method)) {
1458 ret = -LTTNG_ERR_INVALID;
1459 goto end;
1460 }
1461 break;
1462 default:
1463 ret = -LTTNG_ERR_INVALID;
1464 goto end;
1465 }
1466
1467 ret = sizeof(*lookup_comm);
1468 end:
1469 return ret;
1470 }
1471
1472 LTTNG_HIDDEN
1473 int lttng_userspace_probe_location_create_from_payload(
1474 struct lttng_payload_view *view,
1475 struct lttng_userspace_probe_location **location)
1476 {
1477 struct lttng_userspace_probe_location_lookup_method *lookup_method;
1478 enum lttng_userspace_probe_location_type type;
1479 int consumed = 0;
1480 int ret;
1481 struct lttng_userspace_probe_location_comm *probe_location_comm;
1482 struct lttng_payload_view probe_location_comm_view =
1483 lttng_payload_view_from_view(
1484 view, 0, sizeof(*probe_location_comm));
1485
1486 LTTNG_ASSERT(view);
1487 LTTNG_ASSERT(location);
1488
1489 lookup_method = NULL;
1490
1491 if (!lttng_payload_view_is_valid(&probe_location_comm_view)) {
1492 ret = -LTTNG_ERR_INVALID;
1493 goto end;
1494 }
1495
1496 probe_location_comm = (typeof(probe_location_comm)) probe_location_comm_view.buffer.data;
1497 type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
1498 consumed += sizeof(*probe_location_comm);
1499
1500 switch (type) {
1501 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1502 {
1503 struct lttng_payload_view location_view =
1504 lttng_payload_view_from_view(
1505 view, consumed, -1);
1506
1507 ret = lttng_userspace_probe_location_function_create_from_payload(
1508 &location_view, location);
1509 if (ret < 0) {
1510 goto end;
1511 }
1512 break;
1513 }
1514 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1515 {
1516 struct lttng_payload_view location_view =
1517 lttng_payload_view_from_view(view, consumed, -1);
1518
1519 ret = lttng_userspace_probe_location_tracepoint_create_from_payload(
1520 &location_view, location);
1521 if (ret < 0) {
1522 goto end;
1523 }
1524 break;
1525 }
1526 default:
1527 ret = -LTTNG_ERR_INVALID;
1528 goto end;
1529 }
1530
1531 consumed += ret;
1532 if (view->buffer.size <= consumed) {
1533 ret = -LTTNG_ERR_INVALID;
1534 goto end;
1535 }
1536
1537 {
1538 struct lttng_payload_view lookup_method_view =
1539 lttng_payload_view_from_view(
1540 view, consumed, -1);
1541
1542 ret = lttng_userspace_probe_location_lookup_method_create_from_payload(
1543 &lookup_method_view, &lookup_method);
1544 }
1545 if (ret < 0) {
1546 ret = -LTTNG_ERR_INVALID;
1547 goto end;
1548 }
1549
1550 LTTNG_ASSERT(lookup_method);
1551 (*location)->lookup_method = lookup_method;
1552 lookup_method = NULL;
1553 ret += consumed;
1554 end:
1555 return ret;
1556 }
1557
1558 static
1559 int lttng_userspace_probe_location_function_set_binary_fd_handle(
1560 struct lttng_userspace_probe_location *location,
1561 struct fd_handle *binary_fd)
1562 {
1563 int ret = 0;
1564 struct lttng_userspace_probe_location_function *function_location;
1565
1566 LTTNG_ASSERT(location);
1567 LTTNG_ASSERT(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1568
1569 function_location = container_of(location,
1570 struct lttng_userspace_probe_location_function, parent);
1571 fd_handle_put(function_location->binary_fd_handle);
1572 fd_handle_get(binary_fd);
1573 function_location->binary_fd_handle = binary_fd;
1574 return ret;
1575 }
1576
1577 static
1578 int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
1579 struct lttng_userspace_probe_location *location,
1580 struct fd_handle *binary_fd)
1581 {
1582 int ret = 0;
1583 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
1584
1585 LTTNG_ASSERT(location);
1586 LTTNG_ASSERT(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1587
1588 tracepoint_location = container_of(location,
1589 struct lttng_userspace_probe_location_tracepoint, parent);
1590 fd_handle_put(tracepoint_location->binary_fd_handle);
1591 fd_handle_get(binary_fd);
1592 tracepoint_location->binary_fd_handle = binary_fd;
1593 return ret;
1594 }
1595
1596 static
1597 int lttng_userspace_probe_location_function_flatten(
1598 const struct lttng_userspace_probe_location *location,
1599 struct lttng_dynamic_buffer *buffer)
1600 {
1601 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method;
1602 struct lttng_userspace_probe_location_function *probe_function;
1603 struct lttng_userspace_probe_location_function flat_probe;
1604 size_t function_name_len, binary_path_len;
1605 size_t padding_needed = 0;
1606 char *flat_probe_start;
1607 int storage_needed = 0;
1608 int ret;
1609
1610 LTTNG_ASSERT(location);
1611
1612 if (location->lookup_method && location->lookup_method->type !=
1613 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF) {
1614 ret = -LTTNG_ERR_INVALID;
1615 goto end;
1616 }
1617
1618 probe_function = container_of(location,
1619 struct lttng_userspace_probe_location_function,
1620 parent);
1621 LTTNG_ASSERT(probe_function->function_name);
1622 LTTNG_ASSERT(probe_function->binary_path);
1623
1624 storage_needed +=
1625 sizeof(struct lttng_userspace_probe_location_function);
1626 function_name_len = strlen(probe_function->function_name) + 1;
1627 binary_path_len = strlen(probe_function->binary_path) + 1;
1628 storage_needed += function_name_len + binary_path_len;
1629
1630 /*
1631 * The lookup method is aligned to 64-bit within the buffer.
1632 * This is needed even if there is no lookup method since
1633 * the next structure in the buffer probably needs to be
1634 * aligned too (depending on the arch).
1635 */
1636 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1637 storage_needed += padding_needed;
1638
1639 if (location->lookup_method) {
1640 /* NOTE: elf look-up method is assumed here. */
1641 storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1642 }
1643
1644 if (!buffer) {
1645 ret = storage_needed;
1646 goto end;
1647 }
1648
1649 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1650 ret = lttng_dynamic_buffer_set_capacity(buffer,
1651 buffer->size + storage_needed);
1652 if (ret) {
1653 goto end;
1654 }
1655 }
1656
1657 memset(&flat_probe, 0, sizeof(flat_probe));
1658
1659 flat_probe_start = buffer->data + buffer->size;
1660 flat_probe.parent.type = location->type;
1661 /*
1662 * The lookup method, if present, is the last element in the flat
1663 * representation of the probe.
1664 */
1665 if (location->lookup_method) {
1666 flat_probe.parent.lookup_method =
1667 (struct lttng_userspace_probe_location_lookup_method *)
1668 (flat_probe_start + sizeof(flat_probe) +
1669 function_name_len + binary_path_len + padding_needed);
1670 } else {
1671 flat_probe.parent.lookup_method = NULL;
1672 }
1673
1674 flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
1675 flat_probe.binary_path = flat_probe.function_name + function_name_len;
1676 flat_probe.binary_fd_handle = NULL;
1677 ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
1678 sizeof(flat_probe));
1679 if (ret) {
1680 goto end;
1681 }
1682
1683 ret = lttng_dynamic_buffer_append(buffer,
1684 probe_function->function_name, function_name_len);
1685 if (ret) {
1686 goto end;
1687 }
1688 ret = lttng_dynamic_buffer_append(buffer,
1689 probe_function->binary_path, binary_path_len);
1690 if (ret) {
1691 goto end;
1692 }
1693
1694 /* Insert padding before the lookup method. */
1695 ret = lttng_dynamic_buffer_set_size(buffer,
1696 buffer->size + padding_needed);
1697 if (ret) {
1698 goto end;
1699 }
1700
1701 if (!location->lookup_method) {
1702 /* Not an error, the default method is used. */
1703 ret = storage_needed;
1704 goto end;
1705 }
1706
1707 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1708 flat_lookup_method.parent.type =
1709 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
1710 ret = lttng_dynamic_buffer_append(buffer,
1711 &flat_lookup_method, sizeof(flat_lookup_method));
1712 if (ret) {
1713 goto end;
1714 }
1715 ret = storage_needed;
1716 end:
1717 return ret;
1718 }
1719
1720 static
1721 int lttng_userspace_probe_location_tracepoint_flatten(
1722 const struct lttng_userspace_probe_location *location,
1723 struct lttng_dynamic_buffer *buffer)
1724 {
1725 struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method;
1726 struct lttng_userspace_probe_location_tracepoint *probe_tracepoint;
1727 struct lttng_userspace_probe_location_tracepoint flat_probe;
1728 size_t probe_name_len, provider_name_len, binary_path_len;
1729 size_t padding_needed = 0;
1730 int storage_needed = 0;
1731 char *flat_probe_start;
1732 int ret = 0;
1733
1734 LTTNG_ASSERT(location);
1735
1736 /* Only SDT tracepoints are supported at the moment */
1737 if (location->lookup_method && location->lookup_method->type !=
1738 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT) {
1739 ret = -LTTNG_ERR_INVALID;
1740 goto end;
1741 }
1742 probe_tracepoint = container_of(location,
1743 struct lttng_userspace_probe_location_tracepoint,
1744 parent);
1745 LTTNG_ASSERT(probe_tracepoint->probe_name);
1746 LTTNG_ASSERT(probe_tracepoint->provider_name);
1747 LTTNG_ASSERT(probe_tracepoint->binary_path);
1748
1749 /* Compute the storage space needed to flatten the probe location */
1750 storage_needed += sizeof(struct lttng_userspace_probe_location_tracepoint);
1751
1752 probe_name_len = strlen(probe_tracepoint->probe_name) + 1;
1753 provider_name_len = strlen(probe_tracepoint->provider_name) + 1;
1754 binary_path_len = strlen(probe_tracepoint->binary_path) + 1;
1755
1756 storage_needed += probe_name_len + provider_name_len + binary_path_len;
1757
1758 /*
1759 * The lookup method is aligned to 64-bit within the buffer.
1760 * This is needed even if there is no lookup method since
1761 * the next structure in the buffer probably needs to be
1762 * aligned too (depending on the arch).
1763 */
1764 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1765 storage_needed += padding_needed;
1766
1767 if (location->lookup_method) {
1768 /* NOTE: elf look-up method is assumed here. */
1769 storage_needed +=
1770 sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1771 }
1772
1773 /*
1774 * If the caller set buffer to NULL, return the size of the needed buffer.
1775 */
1776 if (!buffer) {
1777 ret = storage_needed;
1778 goto end;
1779 }
1780
1781 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1782 ret = lttng_dynamic_buffer_set_capacity(buffer,
1783 buffer->size + storage_needed);
1784 if (ret) {
1785 goto end;
1786 }
1787 }
1788
1789 memset(&flat_probe, 0, sizeof(flat_probe));
1790
1791 flat_probe_start = buffer->data + buffer->size;
1792 flat_probe.parent.type = location->type;
1793
1794 /*
1795 * The lookup method, if present, is the last element in the flat
1796 * representation of the probe.
1797 */
1798 if (location->lookup_method) {
1799 flat_probe.parent.lookup_method =
1800 (struct lttng_userspace_probe_location_lookup_method *)
1801 (flat_probe_start + sizeof(flat_probe) +
1802 probe_name_len + provider_name_len +
1803 binary_path_len + padding_needed);
1804 } else {
1805 flat_probe.parent.lookup_method = NULL;
1806 }
1807
1808 flat_probe.probe_name = flat_probe_start + sizeof(flat_probe);
1809 flat_probe.provider_name = flat_probe.probe_name + probe_name_len;
1810 flat_probe.binary_path = flat_probe.provider_name + provider_name_len;
1811 flat_probe.binary_fd_handle = NULL;
1812 ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe));
1813 if (ret) {
1814 goto end;
1815 }
1816
1817 /* Append all the fields to the buffer */
1818 ret = lttng_dynamic_buffer_append(buffer,
1819 probe_tracepoint->probe_name, probe_name_len);
1820 if (ret) {
1821 goto end;
1822 }
1823 ret = lttng_dynamic_buffer_append(buffer,
1824 probe_tracepoint->provider_name, provider_name_len);
1825 if (ret) {
1826 goto end;
1827 }
1828 ret = lttng_dynamic_buffer_append(buffer,
1829 probe_tracepoint->binary_path, binary_path_len);
1830 if (ret) {
1831 goto end;
1832 }
1833
1834 /* Insert padding before the lookup method. */
1835 ret = lttng_dynamic_buffer_set_size(buffer, buffer->size + padding_needed);
1836 if (ret) {
1837 goto end;
1838 }
1839
1840 if (!location->lookup_method) {
1841 /* Not an error, the default method is used. */
1842 ret = storage_needed;
1843 goto end;
1844 }
1845
1846 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1847
1848 flat_lookup_method.parent.type =
1849 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
1850 ret = lttng_dynamic_buffer_append(buffer,
1851 &flat_lookup_method, sizeof(flat_lookup_method));
1852 if (ret) {
1853 goto end;
1854 }
1855 ret = storage_needed;
1856 end:
1857 return ret;
1858 }
1859
1860 LTTNG_HIDDEN
1861 int lttng_userspace_probe_location_flatten(
1862 const struct lttng_userspace_probe_location *location,
1863 struct lttng_dynamic_buffer *buffer)
1864 {
1865 int ret;
1866 if (!location) {
1867 ret = -LTTNG_ERR_INVALID;
1868 goto end;
1869 }
1870
1871 /* Only types currently supported. */
1872 switch (location->type) {
1873 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1874 ret = lttng_userspace_probe_location_function_flatten(location, buffer);
1875 break;
1876 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1877 ret = lttng_userspace_probe_location_tracepoint_flatten(location, buffer);
1878 break;
1879 default:
1880 ret = -LTTNG_ERR_INVALID;
1881 goto end;
1882 }
1883
1884 end:
1885 return ret;
1886 }
1887
1888 LTTNG_HIDDEN
1889 struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
1890 const struct lttng_userspace_probe_location *location)
1891 {
1892 struct lttng_userspace_probe_location *new_location = NULL;
1893 enum lttng_userspace_probe_location_type type;
1894
1895 if (!location) {
1896 goto err;
1897 }
1898
1899 type = lttng_userspace_probe_location_get_type(location);
1900 switch (type) {
1901 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1902 new_location =
1903 lttng_userspace_probe_location_function_copy(location);
1904 if (!new_location) {
1905 goto err;
1906 }
1907 break;
1908 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1909 new_location =
1910 lttng_userspace_probe_location_tracepoint_copy(location);
1911 if (!new_location) {
1912 goto err;
1913 }
1914 break;
1915 default:
1916 new_location = NULL;
1917 goto err;
1918 }
1919 err:
1920 return new_location;
1921 }
1922
1923 LTTNG_HIDDEN
1924 bool lttng_userspace_probe_location_lookup_method_is_equal(
1925 const struct lttng_userspace_probe_location_lookup_method *a,
1926 const struct lttng_userspace_probe_location_lookup_method *b)
1927 {
1928 bool is_equal = false;
1929
1930 if (!a || !b) {
1931 goto end;
1932 }
1933
1934 if (a == b) {
1935 is_equal = true;
1936 goto end;
1937 }
1938
1939 if (a->type != b->type) {
1940 goto end;
1941 }
1942
1943 is_equal = true;
1944 end:
1945 return is_equal;
1946 }
1947
1948 LTTNG_HIDDEN
1949 bool lttng_userspace_probe_location_is_equal(
1950 const struct lttng_userspace_probe_location *a,
1951 const struct lttng_userspace_probe_location *b)
1952 {
1953 bool is_equal = false;
1954
1955 if (!a || !b) {
1956 goto end;
1957 }
1958
1959 if (a == b) {
1960 is_equal = true;
1961 goto end;
1962 }
1963
1964 if (!lttng_userspace_probe_location_lookup_method_is_equal(
1965 a->lookup_method, b->lookup_method)) {
1966 goto end;
1967 }
1968
1969 if (a->type != b->type) {
1970 goto end;
1971 }
1972
1973 is_equal = a->equal ? a->equal(a, b) : true;
1974 end:
1975 return is_equal;
1976 }
1977
1978 LTTNG_HIDDEN
1979 unsigned long lttng_userspace_probe_location_hash(
1980 const struct lttng_userspace_probe_location *location)
1981 {
1982 return location->hash(location);
1983 }
1984
1985 LTTNG_HIDDEN
1986 enum lttng_error_code lttng_userspace_probe_location_mi_serialize(
1987 const struct lttng_userspace_probe_location *location,
1988 struct mi_writer *writer)
1989 {
1990 typedef enum lttng_error_code (*mi_fp)(
1991 const struct lttng_userspace_probe_location *,
1992 struct mi_writer *);
1993
1994 int ret;
1995 enum lttng_error_code ret_code;
1996 mi_fp mi_function = NULL;
1997
1998 LTTNG_ASSERT(location);
1999 LTTNG_ASSERT(writer);
2000
2001 switch (lttng_userspace_probe_location_get_type(location)) {
2002 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
2003 mi_function = lttng_userspace_probe_location_function_mi_serialize;
2004 break;
2005 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
2006 mi_function = lttng_userspace_probe_location_tracepoint_mi_serialize;
2007 break;
2008 default:
2009 abort();
2010 break;
2011 }
2012
2013 /* Open userspace probe location element. */
2014 ret = mi_lttng_writer_open_element(
2015 writer, mi_lttng_element_userspace_probe_location);
2016 if (ret) {
2017 goto mi_error;
2018 }
2019
2020 /* Underlying user space probe location. */
2021 ret_code = mi_function(location, writer);
2022 if (ret_code != LTTNG_OK) {
2023 goto end;
2024 }
2025
2026 /* Close userspace probe location element. */
2027 ret = mi_lttng_writer_close_element(writer);
2028 if (ret) {
2029 goto mi_error;
2030 }
2031
2032 ret_code = LTTNG_OK;
2033 goto end;
2034
2035 mi_error:
2036 ret_code = LTTNG_ERR_MI_IO_FAIL;
2037 end:
2038 return ret_code;
2039 }
2040
2041 enum lttng_error_code lttng_userspace_probe_location_lookup_method_mi_serialize(
2042 const struct lttng_userspace_probe_location_lookup_method
2043 *method,
2044 struct mi_writer *writer)
2045 {
2046 int ret;
2047 enum lttng_error_code ret_code;
2048 const char *type_element_str;
2049
2050 LTTNG_ASSERT(method);
2051 LTTNG_ASSERT(writer);
2052
2053 switch (lttng_userspace_probe_location_lookup_method_get_type(method)) {
2054 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
2055 type_element_str =
2056 mi_lttng_element_userspace_probe_location_lookup_method_function_default;
2057 break;
2058 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
2059 type_element_str =
2060 mi_lttng_element_userspace_probe_location_lookup_method_function_elf;
2061 break;
2062 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
2063 type_element_str =
2064 mi_lttng_element_userspace_probe_location_lookup_method_tracepoint_sdt;
2065 break;
2066 default:
2067 abort();
2068 break;
2069 }
2070
2071 /* Open userspace probe location lookup method element. */
2072 ret = mi_lttng_writer_open_element(writer,
2073 mi_lttng_element_userspace_probe_location_lookup_method);
2074 if (ret) {
2075 goto mi_error;
2076 }
2077
2078 /* User space probe location lookup method empty element. */
2079 ret = mi_lttng_writer_open_element(writer, type_element_str);
2080 if (ret) {
2081 goto mi_error;
2082 }
2083
2084 /* Close userspace probe location lookup method element. */
2085 ret = mi_lttng_close_multi_element(writer, 2);
2086 if (ret) {
2087 goto mi_error;
2088 }
2089
2090 ret_code = LTTNG_OK;
2091 goto end;
2092
2093 mi_error:
2094 ret_code = LTTNG_ERR_MI_IO_FAIL;
2095 end:
2096 return ret_code;
2097 }
2098
2099 static enum lttng_error_code lttng_userspace_probe_location_tracepoint_mi_serialize(
2100 const struct lttng_userspace_probe_location *location,
2101 struct mi_writer *writer)
2102 {
2103 int ret;
2104 enum lttng_error_code ret_code;
2105 const char *probe_name = NULL;
2106 const char *provider_name = NULL;
2107 const char *binary_path = NULL;
2108 const struct lttng_userspace_probe_location_lookup_method
2109 *lookup_method = NULL;
2110
2111 LTTNG_ASSERT(location);
2112 LTTNG_ASSERT(writer);
2113
2114 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(
2115 location);
2116 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(
2117 location);
2118 binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(
2119 location);
2120 lookup_method = lttng_userspace_probe_location_tracepoint_get_lookup_method(
2121 location);
2122
2123 /* Open userspace probe location tracepoint element. */
2124 ret = mi_lttng_writer_open_element(writer,
2125 mi_lttng_element_userspace_probe_location_tracepoint);
2126 if (ret) {
2127 goto mi_error;
2128 }
2129
2130 /* Probe name. */
2131 ret = mi_lttng_writer_write_element_string(writer,
2132 mi_lttng_element_userspace_probe_location_tracepoint_probe_name,
2133 probe_name);
2134 if (ret) {
2135 goto mi_error;
2136 }
2137
2138 /* Provider name. */
2139 ret = mi_lttng_writer_write_element_string(writer,
2140 mi_lttng_element_userspace_probe_location_tracepoint_provider_name,
2141 provider_name);
2142 if (ret) {
2143 goto mi_error;
2144 }
2145
2146 /* Binary path. */
2147 ret = mi_lttng_writer_write_element_string(writer,
2148 mi_lttng_element_userspace_probe_location_binary_path,
2149 binary_path);
2150 if (ret) {
2151 goto mi_error;
2152 }
2153
2154 /* The lookup method. */
2155 ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize(
2156 lookup_method, writer);
2157 if (ret_code != LTTNG_OK) {
2158 goto end;
2159 }
2160
2161 /* Close userspace probe location tracepoint. */
2162 ret = mi_lttng_writer_close_element(writer);
2163 if (ret) {
2164 goto mi_error;
2165 }
2166
2167 ret_code = LTTNG_OK;
2168 goto end;
2169
2170 mi_error:
2171 ret_code = LTTNG_ERR_MI_IO_FAIL;
2172 end:
2173 return ret_code;
2174 }
2175
2176 static enum lttng_error_code lttng_userspace_probe_location_function_mi_serialize(
2177 const struct lttng_userspace_probe_location *location,
2178 struct mi_writer *writer)
2179 {
2180 int ret;
2181 enum lttng_error_code ret_code;
2182 const char *function_name = NULL;
2183 const char *binary_path = NULL;
2184 const char *instrumentation_type_str = NULL;
2185 enum lttng_userspace_probe_location_function_instrumentation_type
2186 instrumentation_type;
2187 const struct lttng_userspace_probe_location_lookup_method
2188 *lookup_method = NULL;
2189
2190 LTTNG_ASSERT(location);
2191 LTTNG_ASSERT(writer);
2192
2193 function_name = lttng_userspace_probe_location_function_get_function_name(
2194 location);
2195 binary_path = lttng_userspace_probe_location_function_get_binary_path(
2196 location);
2197 instrumentation_type =
2198 lttng_userspace_probe_location_function_get_instrumentation_type(
2199 location);
2200 lookup_method = lttng_userspace_probe_location_function_get_lookup_method(
2201 location);
2202
2203 switch (instrumentation_type) {
2204 case LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY:
2205 instrumentation_type_str =
2206 mi_lttng_userspace_probe_location_function_instrumentation_type_entry;
2207 break;
2208 default:
2209 abort();
2210 break;
2211 }
2212
2213 /* Open userspace probe location function element. */
2214 ret = mi_lttng_writer_open_element(writer,
2215 mi_lttng_element_userspace_probe_location_function);
2216 if (ret) {
2217 goto mi_error;
2218 }
2219
2220 /* Function name. */
2221 ret = mi_lttng_writer_write_element_string(writer,
2222 mi_lttng_element_userspace_probe_location_function_name,
2223 function_name);
2224 if (ret) {
2225 goto mi_error;
2226 }
2227
2228 /* Binary path. */
2229 ret = mi_lttng_writer_write_element_string(writer,
2230 mi_lttng_element_userspace_probe_location_binary_path,
2231 binary_path);
2232 if (ret) {
2233 goto mi_error;
2234 }
2235
2236 /* Instrumentation type. */
2237 ret = mi_lttng_writer_write_element_string(writer,
2238 mi_lttng_element_userspace_probe_location_function_instrumentation_type,
2239 instrumentation_type_str);
2240 if (ret) {
2241 goto mi_error;
2242 }
2243
2244 /* The lookup method. */
2245 ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize(
2246 lookup_method, writer);
2247 if (ret_code != LTTNG_OK) {
2248 goto end;
2249 }
2250
2251 /* Close userspace probe location function element. */
2252 ret = mi_lttng_writer_close_element(writer);
2253 if (ret) {
2254 goto mi_error;
2255 }
2256
2257 ret_code = LTTNG_OK;
2258 goto end;
2259
2260 mi_error:
2261 ret_code = LTTNG_ERR_MI_IO_FAIL;
2262 end:
2263 return ret_code;
2264 }
This page took 0.11172 seconds and 5 git commands to generate.