Fix: userspace-probe: unreported error on string copy error
[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("Failed to allocate probe name");
1385 ret = -LTTNG_ERR_INVALID;
1386 goto end;
1387 }
1388 provider_name = lttng_strndup(provider_name_src, LTTNG_SYMBOL_NAME_LEN);
1389 if (!provider_name) {
1390 PERROR("Failed to allocate provider name");
1391 ret = -LTTNG_ERR_INVALID;
1392 goto end;
1393 }
1394
1395 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1396 if (!binary_path) {
1397 PERROR("Failed to allocate binary path");
1398 ret = -LTTNG_ERR_INVALID;
1399 goto end;
1400 }
1401
1402 *location = lttng_userspace_probe_location_tracepoint_create_no_check(
1403 binary_path, provider_name, probe_name, NULL, false);
1404 if (!(*location)) {
1405 ret = -LTTNG_ERR_INVALID;
1406 goto end;
1407 }
1408
1409 ret = lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
1410 *location, binary_fd_handle);
1411 if (ret) {
1412 ret = -LTTNG_ERR_INVALID;
1413 goto end;
1414 }
1415
1416 ret = (int) expected_size;
1417 end:
1418 fd_handle_put(binary_fd_handle);
1419 free(probe_name);
1420 free(provider_name);
1421 free(binary_path);
1422 return ret;
1423 }
1424
1425 static
1426 int lttng_userspace_probe_location_lookup_method_create_from_payload(
1427 struct lttng_payload_view *view,
1428 struct lttng_userspace_probe_location_lookup_method **lookup_method)
1429 {
1430 int ret;
1431 struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
1432 enum lttng_userspace_probe_location_lookup_method_type type;
1433
1434 LTTNG_ASSERT(view);
1435 LTTNG_ASSERT(lookup_method);
1436
1437 if (view->buffer.size < sizeof(*lookup_comm)) {
1438 ret = -LTTNG_ERR_INVALID;
1439 goto end;
1440 }
1441
1442 lookup_comm = (typeof(lookup_comm)) view->buffer.data;
1443 type = (enum lttng_userspace_probe_location_lookup_method_type)
1444 lookup_comm->type;
1445 switch (type) {
1446 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
1447 *lookup_method = NULL;
1448 break;
1449 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
1450 *lookup_method =
1451 lttng_userspace_probe_location_lookup_method_function_elf_create();
1452 if (!(*lookup_method)) {
1453 ret = -LTTNG_ERR_INVALID;
1454 goto end;
1455 }
1456 break;
1457 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
1458 *lookup_method =
1459 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1460 if (!(*lookup_method)) {
1461 ret = -LTTNG_ERR_INVALID;
1462 goto end;
1463 }
1464 break;
1465 default:
1466 ret = -LTTNG_ERR_INVALID;
1467 goto end;
1468 }
1469
1470 ret = sizeof(*lookup_comm);
1471 end:
1472 return ret;
1473 }
1474
1475 LTTNG_HIDDEN
1476 int lttng_userspace_probe_location_create_from_payload(
1477 struct lttng_payload_view *view,
1478 struct lttng_userspace_probe_location **location)
1479 {
1480 struct lttng_userspace_probe_location_lookup_method *lookup_method;
1481 enum lttng_userspace_probe_location_type type;
1482 int consumed = 0;
1483 int ret;
1484 struct lttng_userspace_probe_location_comm *probe_location_comm;
1485 struct lttng_payload_view probe_location_comm_view =
1486 lttng_payload_view_from_view(
1487 view, 0, sizeof(*probe_location_comm));
1488
1489 LTTNG_ASSERT(view);
1490 LTTNG_ASSERT(location);
1491
1492 lookup_method = NULL;
1493
1494 if (!lttng_payload_view_is_valid(&probe_location_comm_view)) {
1495 ret = -LTTNG_ERR_INVALID;
1496 goto end;
1497 }
1498
1499 probe_location_comm = (typeof(probe_location_comm)) probe_location_comm_view.buffer.data;
1500 type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
1501 consumed += sizeof(*probe_location_comm);
1502
1503 switch (type) {
1504 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1505 {
1506 struct lttng_payload_view location_view =
1507 lttng_payload_view_from_view(
1508 view, consumed, -1);
1509
1510 ret = lttng_userspace_probe_location_function_create_from_payload(
1511 &location_view, location);
1512 if (ret < 0) {
1513 goto end;
1514 }
1515 break;
1516 }
1517 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1518 {
1519 struct lttng_payload_view location_view =
1520 lttng_payload_view_from_view(view, consumed, -1);
1521
1522 ret = lttng_userspace_probe_location_tracepoint_create_from_payload(
1523 &location_view, location);
1524 if (ret < 0) {
1525 goto end;
1526 }
1527 break;
1528 }
1529 default:
1530 ret = -LTTNG_ERR_INVALID;
1531 goto end;
1532 }
1533
1534 consumed += ret;
1535 if (view->buffer.size <= consumed) {
1536 ret = -LTTNG_ERR_INVALID;
1537 goto end;
1538 }
1539
1540 {
1541 struct lttng_payload_view lookup_method_view =
1542 lttng_payload_view_from_view(
1543 view, consumed, -1);
1544
1545 ret = lttng_userspace_probe_location_lookup_method_create_from_payload(
1546 &lookup_method_view, &lookup_method);
1547 }
1548 if (ret < 0) {
1549 ret = -LTTNG_ERR_INVALID;
1550 goto end;
1551 }
1552
1553 LTTNG_ASSERT(lookup_method);
1554 (*location)->lookup_method = lookup_method;
1555 lookup_method = NULL;
1556 ret += consumed;
1557 end:
1558 return ret;
1559 }
1560
1561 static
1562 int lttng_userspace_probe_location_function_set_binary_fd_handle(
1563 struct lttng_userspace_probe_location *location,
1564 struct fd_handle *binary_fd)
1565 {
1566 int ret = 0;
1567 struct lttng_userspace_probe_location_function *function_location;
1568
1569 LTTNG_ASSERT(location);
1570 LTTNG_ASSERT(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1571
1572 function_location = container_of(location,
1573 struct lttng_userspace_probe_location_function, parent);
1574 fd_handle_put(function_location->binary_fd_handle);
1575 fd_handle_get(binary_fd);
1576 function_location->binary_fd_handle = binary_fd;
1577 return ret;
1578 }
1579
1580 static
1581 int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
1582 struct lttng_userspace_probe_location *location,
1583 struct fd_handle *binary_fd)
1584 {
1585 int ret = 0;
1586 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
1587
1588 LTTNG_ASSERT(location);
1589 LTTNG_ASSERT(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1590
1591 tracepoint_location = container_of(location,
1592 struct lttng_userspace_probe_location_tracepoint, parent);
1593 fd_handle_put(tracepoint_location->binary_fd_handle);
1594 fd_handle_get(binary_fd);
1595 tracepoint_location->binary_fd_handle = binary_fd;
1596 return ret;
1597 }
1598
1599 static
1600 int lttng_userspace_probe_location_function_flatten(
1601 const struct lttng_userspace_probe_location *location,
1602 struct lttng_dynamic_buffer *buffer)
1603 {
1604 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method;
1605 struct lttng_userspace_probe_location_function *probe_function;
1606 struct lttng_userspace_probe_location_function flat_probe;
1607 size_t function_name_len, binary_path_len;
1608 size_t padding_needed = 0;
1609 char *flat_probe_start;
1610 int storage_needed = 0;
1611 int ret;
1612
1613 LTTNG_ASSERT(location);
1614
1615 if (location->lookup_method && location->lookup_method->type !=
1616 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF) {
1617 ret = -LTTNG_ERR_INVALID;
1618 goto end;
1619 }
1620
1621 probe_function = container_of(location,
1622 struct lttng_userspace_probe_location_function,
1623 parent);
1624 LTTNG_ASSERT(probe_function->function_name);
1625 LTTNG_ASSERT(probe_function->binary_path);
1626
1627 storage_needed +=
1628 sizeof(struct lttng_userspace_probe_location_function);
1629 function_name_len = strlen(probe_function->function_name) + 1;
1630 binary_path_len = strlen(probe_function->binary_path) + 1;
1631 storage_needed += function_name_len + binary_path_len;
1632
1633 /*
1634 * The lookup method is aligned to 64-bit within the buffer.
1635 * This is needed even if there is no lookup method since
1636 * the next structure in the buffer probably needs to be
1637 * aligned too (depending on the arch).
1638 */
1639 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1640 storage_needed += padding_needed;
1641
1642 if (location->lookup_method) {
1643 /* NOTE: elf look-up method is assumed here. */
1644 storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1645 }
1646
1647 if (!buffer) {
1648 ret = storage_needed;
1649 goto end;
1650 }
1651
1652 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1653 ret = lttng_dynamic_buffer_set_capacity(buffer,
1654 buffer->size + storage_needed);
1655 if (ret) {
1656 goto end;
1657 }
1658 }
1659
1660 memset(&flat_probe, 0, sizeof(flat_probe));
1661
1662 flat_probe_start = buffer->data + buffer->size;
1663 flat_probe.parent.type = location->type;
1664 /*
1665 * The lookup method, if present, is the last element in the flat
1666 * representation of the probe.
1667 */
1668 if (location->lookup_method) {
1669 flat_probe.parent.lookup_method =
1670 (struct lttng_userspace_probe_location_lookup_method *)
1671 (flat_probe_start + sizeof(flat_probe) +
1672 function_name_len + binary_path_len + padding_needed);
1673 } else {
1674 flat_probe.parent.lookup_method = NULL;
1675 }
1676
1677 flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
1678 flat_probe.binary_path = flat_probe.function_name + function_name_len;
1679 flat_probe.binary_fd_handle = NULL;
1680 ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
1681 sizeof(flat_probe));
1682 if (ret) {
1683 goto end;
1684 }
1685
1686 ret = lttng_dynamic_buffer_append(buffer,
1687 probe_function->function_name, function_name_len);
1688 if (ret) {
1689 goto end;
1690 }
1691 ret = lttng_dynamic_buffer_append(buffer,
1692 probe_function->binary_path, binary_path_len);
1693 if (ret) {
1694 goto end;
1695 }
1696
1697 /* Insert padding before the lookup method. */
1698 ret = lttng_dynamic_buffer_set_size(buffer,
1699 buffer->size + padding_needed);
1700 if (ret) {
1701 goto end;
1702 }
1703
1704 if (!location->lookup_method) {
1705 /* Not an error, the default method is used. */
1706 ret = storage_needed;
1707 goto end;
1708 }
1709
1710 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1711 flat_lookup_method.parent.type =
1712 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
1713 ret = lttng_dynamic_buffer_append(buffer,
1714 &flat_lookup_method, sizeof(flat_lookup_method));
1715 if (ret) {
1716 goto end;
1717 }
1718 ret = storage_needed;
1719 end:
1720 return ret;
1721 }
1722
1723 static
1724 int lttng_userspace_probe_location_tracepoint_flatten(
1725 const struct lttng_userspace_probe_location *location,
1726 struct lttng_dynamic_buffer *buffer)
1727 {
1728 struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method;
1729 struct lttng_userspace_probe_location_tracepoint *probe_tracepoint;
1730 struct lttng_userspace_probe_location_tracepoint flat_probe;
1731 size_t probe_name_len, provider_name_len, binary_path_len;
1732 size_t padding_needed = 0;
1733 int storage_needed = 0;
1734 char *flat_probe_start;
1735 int ret = 0;
1736
1737 LTTNG_ASSERT(location);
1738
1739 /* Only SDT tracepoints are supported at the moment */
1740 if (location->lookup_method && location->lookup_method->type !=
1741 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT) {
1742 ret = -LTTNG_ERR_INVALID;
1743 goto end;
1744 }
1745 probe_tracepoint = container_of(location,
1746 struct lttng_userspace_probe_location_tracepoint,
1747 parent);
1748 LTTNG_ASSERT(probe_tracepoint->probe_name);
1749 LTTNG_ASSERT(probe_tracepoint->provider_name);
1750 LTTNG_ASSERT(probe_tracepoint->binary_path);
1751
1752 /* Compute the storage space needed to flatten the probe location */
1753 storage_needed += sizeof(struct lttng_userspace_probe_location_tracepoint);
1754
1755 probe_name_len = strlen(probe_tracepoint->probe_name) + 1;
1756 provider_name_len = strlen(probe_tracepoint->provider_name) + 1;
1757 binary_path_len = strlen(probe_tracepoint->binary_path) + 1;
1758
1759 storage_needed += probe_name_len + provider_name_len + binary_path_len;
1760
1761 /*
1762 * The lookup method is aligned to 64-bit within the buffer.
1763 * This is needed even if there is no lookup method since
1764 * the next structure in the buffer probably needs to be
1765 * aligned too (depending on the arch).
1766 */
1767 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1768 storage_needed += padding_needed;
1769
1770 if (location->lookup_method) {
1771 /* NOTE: elf look-up method is assumed here. */
1772 storage_needed +=
1773 sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1774 }
1775
1776 /*
1777 * If the caller set buffer to NULL, return the size of the needed buffer.
1778 */
1779 if (!buffer) {
1780 ret = storage_needed;
1781 goto end;
1782 }
1783
1784 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1785 ret = lttng_dynamic_buffer_set_capacity(buffer,
1786 buffer->size + storage_needed);
1787 if (ret) {
1788 goto end;
1789 }
1790 }
1791
1792 memset(&flat_probe, 0, sizeof(flat_probe));
1793
1794 flat_probe_start = buffer->data + buffer->size;
1795 flat_probe.parent.type = location->type;
1796
1797 /*
1798 * The lookup method, if present, is the last element in the flat
1799 * representation of the probe.
1800 */
1801 if (location->lookup_method) {
1802 flat_probe.parent.lookup_method =
1803 (struct lttng_userspace_probe_location_lookup_method *)
1804 (flat_probe_start + sizeof(flat_probe) +
1805 probe_name_len + provider_name_len +
1806 binary_path_len + padding_needed);
1807 } else {
1808 flat_probe.parent.lookup_method = NULL;
1809 }
1810
1811 flat_probe.probe_name = flat_probe_start + sizeof(flat_probe);
1812 flat_probe.provider_name = flat_probe.probe_name + probe_name_len;
1813 flat_probe.binary_path = flat_probe.provider_name + provider_name_len;
1814 flat_probe.binary_fd_handle = NULL;
1815 ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe));
1816 if (ret) {
1817 goto end;
1818 }
1819
1820 /* Append all the fields to the buffer */
1821 ret = lttng_dynamic_buffer_append(buffer,
1822 probe_tracepoint->probe_name, probe_name_len);
1823 if (ret) {
1824 goto end;
1825 }
1826 ret = lttng_dynamic_buffer_append(buffer,
1827 probe_tracepoint->provider_name, provider_name_len);
1828 if (ret) {
1829 goto end;
1830 }
1831 ret = lttng_dynamic_buffer_append(buffer,
1832 probe_tracepoint->binary_path, binary_path_len);
1833 if (ret) {
1834 goto end;
1835 }
1836
1837 /* Insert padding before the lookup method. */
1838 ret = lttng_dynamic_buffer_set_size(buffer, buffer->size + padding_needed);
1839 if (ret) {
1840 goto end;
1841 }
1842
1843 if (!location->lookup_method) {
1844 /* Not an error, the default method is used. */
1845 ret = storage_needed;
1846 goto end;
1847 }
1848
1849 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1850
1851 flat_lookup_method.parent.type =
1852 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
1853 ret = lttng_dynamic_buffer_append(buffer,
1854 &flat_lookup_method, sizeof(flat_lookup_method));
1855 if (ret) {
1856 goto end;
1857 }
1858 ret = storage_needed;
1859 end:
1860 return ret;
1861 }
1862
1863 LTTNG_HIDDEN
1864 int lttng_userspace_probe_location_flatten(
1865 const struct lttng_userspace_probe_location *location,
1866 struct lttng_dynamic_buffer *buffer)
1867 {
1868 int ret;
1869 if (!location) {
1870 ret = -LTTNG_ERR_INVALID;
1871 goto end;
1872 }
1873
1874 /* Only types currently supported. */
1875 switch (location->type) {
1876 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1877 ret = lttng_userspace_probe_location_function_flatten(location, buffer);
1878 break;
1879 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1880 ret = lttng_userspace_probe_location_tracepoint_flatten(location, buffer);
1881 break;
1882 default:
1883 ret = -LTTNG_ERR_INVALID;
1884 goto end;
1885 }
1886
1887 end:
1888 return ret;
1889 }
1890
1891 LTTNG_HIDDEN
1892 struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
1893 const struct lttng_userspace_probe_location *location)
1894 {
1895 struct lttng_userspace_probe_location *new_location = NULL;
1896 enum lttng_userspace_probe_location_type type;
1897
1898 if (!location) {
1899 goto err;
1900 }
1901
1902 type = lttng_userspace_probe_location_get_type(location);
1903 switch (type) {
1904 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1905 new_location =
1906 lttng_userspace_probe_location_function_copy(location);
1907 if (!new_location) {
1908 goto err;
1909 }
1910 break;
1911 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1912 new_location =
1913 lttng_userspace_probe_location_tracepoint_copy(location);
1914 if (!new_location) {
1915 goto err;
1916 }
1917 break;
1918 default:
1919 new_location = NULL;
1920 goto err;
1921 }
1922 err:
1923 return new_location;
1924 }
1925
1926 LTTNG_HIDDEN
1927 bool lttng_userspace_probe_location_lookup_method_is_equal(
1928 const struct lttng_userspace_probe_location_lookup_method *a,
1929 const struct lttng_userspace_probe_location_lookup_method *b)
1930 {
1931 bool is_equal = false;
1932
1933 if (!a || !b) {
1934 goto end;
1935 }
1936
1937 if (a == b) {
1938 is_equal = true;
1939 goto end;
1940 }
1941
1942 if (a->type != b->type) {
1943 goto end;
1944 }
1945
1946 is_equal = true;
1947 end:
1948 return is_equal;
1949 }
1950
1951 LTTNG_HIDDEN
1952 bool lttng_userspace_probe_location_is_equal(
1953 const struct lttng_userspace_probe_location *a,
1954 const struct lttng_userspace_probe_location *b)
1955 {
1956 bool is_equal = false;
1957
1958 if (!a || !b) {
1959 goto end;
1960 }
1961
1962 if (a == b) {
1963 is_equal = true;
1964 goto end;
1965 }
1966
1967 if (!lttng_userspace_probe_location_lookup_method_is_equal(
1968 a->lookup_method, b->lookup_method)) {
1969 goto end;
1970 }
1971
1972 if (a->type != b->type) {
1973 goto end;
1974 }
1975
1976 is_equal = a->equal ? a->equal(a, b) : true;
1977 end:
1978 return is_equal;
1979 }
1980
1981 LTTNG_HIDDEN
1982 unsigned long lttng_userspace_probe_location_hash(
1983 const struct lttng_userspace_probe_location *location)
1984 {
1985 return location->hash(location);
1986 }
1987
1988 LTTNG_HIDDEN
1989 enum lttng_error_code lttng_userspace_probe_location_mi_serialize(
1990 const struct lttng_userspace_probe_location *location,
1991 struct mi_writer *writer)
1992 {
1993 typedef enum lttng_error_code (*mi_fp)(
1994 const struct lttng_userspace_probe_location *,
1995 struct mi_writer *);
1996
1997 int ret;
1998 enum lttng_error_code ret_code;
1999 mi_fp mi_function = NULL;
2000
2001 LTTNG_ASSERT(location);
2002 LTTNG_ASSERT(writer);
2003
2004 switch (lttng_userspace_probe_location_get_type(location)) {
2005 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
2006 mi_function = lttng_userspace_probe_location_function_mi_serialize;
2007 break;
2008 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
2009 mi_function = lttng_userspace_probe_location_tracepoint_mi_serialize;
2010 break;
2011 default:
2012 abort();
2013 break;
2014 }
2015
2016 /* Open userspace probe location element. */
2017 ret = mi_lttng_writer_open_element(
2018 writer, mi_lttng_element_userspace_probe_location);
2019 if (ret) {
2020 goto mi_error;
2021 }
2022
2023 /* Underlying user space probe location. */
2024 ret_code = mi_function(location, writer);
2025 if (ret_code != LTTNG_OK) {
2026 goto end;
2027 }
2028
2029 /* Close userspace probe location element. */
2030 ret = mi_lttng_writer_close_element(writer);
2031 if (ret) {
2032 goto mi_error;
2033 }
2034
2035 ret_code = LTTNG_OK;
2036 goto end;
2037
2038 mi_error:
2039 ret_code = LTTNG_ERR_MI_IO_FAIL;
2040 end:
2041 return ret_code;
2042 }
2043
2044 enum lttng_error_code lttng_userspace_probe_location_lookup_method_mi_serialize(
2045 const struct lttng_userspace_probe_location_lookup_method
2046 *method,
2047 struct mi_writer *writer)
2048 {
2049 int ret;
2050 enum lttng_error_code ret_code;
2051 const char *type_element_str;
2052
2053 LTTNG_ASSERT(method);
2054 LTTNG_ASSERT(writer);
2055
2056 switch (lttng_userspace_probe_location_lookup_method_get_type(method)) {
2057 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
2058 type_element_str =
2059 mi_lttng_element_userspace_probe_location_lookup_method_function_default;
2060 break;
2061 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
2062 type_element_str =
2063 mi_lttng_element_userspace_probe_location_lookup_method_function_elf;
2064 break;
2065 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
2066 type_element_str =
2067 mi_lttng_element_userspace_probe_location_lookup_method_tracepoint_sdt;
2068 break;
2069 default:
2070 abort();
2071 break;
2072 }
2073
2074 /* Open userspace probe location lookup method element. */
2075 ret = mi_lttng_writer_open_element(writer,
2076 mi_lttng_element_userspace_probe_location_lookup_method);
2077 if (ret) {
2078 goto mi_error;
2079 }
2080
2081 /* User space probe location lookup method empty element. */
2082 ret = mi_lttng_writer_open_element(writer, type_element_str);
2083 if (ret) {
2084 goto mi_error;
2085 }
2086
2087 /* Close userspace probe location lookup method element. */
2088 ret = mi_lttng_close_multi_element(writer, 2);
2089 if (ret) {
2090 goto mi_error;
2091 }
2092
2093 ret_code = LTTNG_OK;
2094 goto end;
2095
2096 mi_error:
2097 ret_code = LTTNG_ERR_MI_IO_FAIL;
2098 end:
2099 return ret_code;
2100 }
2101
2102 static enum lttng_error_code lttng_userspace_probe_location_tracepoint_mi_serialize(
2103 const struct lttng_userspace_probe_location *location,
2104 struct mi_writer *writer)
2105 {
2106 int ret;
2107 enum lttng_error_code ret_code;
2108 const char *probe_name = NULL;
2109 const char *provider_name = NULL;
2110 const char *binary_path = NULL;
2111 const struct lttng_userspace_probe_location_lookup_method
2112 *lookup_method = NULL;
2113
2114 LTTNG_ASSERT(location);
2115 LTTNG_ASSERT(writer);
2116
2117 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(
2118 location);
2119 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(
2120 location);
2121 binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(
2122 location);
2123 lookup_method = lttng_userspace_probe_location_tracepoint_get_lookup_method(
2124 location);
2125
2126 /* Open userspace probe location tracepoint element. */
2127 ret = mi_lttng_writer_open_element(writer,
2128 mi_lttng_element_userspace_probe_location_tracepoint);
2129 if (ret) {
2130 goto mi_error;
2131 }
2132
2133 /* Probe name. */
2134 ret = mi_lttng_writer_write_element_string(writer,
2135 mi_lttng_element_userspace_probe_location_tracepoint_probe_name,
2136 probe_name);
2137 if (ret) {
2138 goto mi_error;
2139 }
2140
2141 /* Provider name. */
2142 ret = mi_lttng_writer_write_element_string(writer,
2143 mi_lttng_element_userspace_probe_location_tracepoint_provider_name,
2144 provider_name);
2145 if (ret) {
2146 goto mi_error;
2147 }
2148
2149 /* Binary path. */
2150 ret = mi_lttng_writer_write_element_string(writer,
2151 mi_lttng_element_userspace_probe_location_binary_path,
2152 binary_path);
2153 if (ret) {
2154 goto mi_error;
2155 }
2156
2157 /* The lookup method. */
2158 ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize(
2159 lookup_method, writer);
2160 if (ret_code != LTTNG_OK) {
2161 goto end;
2162 }
2163
2164 /* Close userspace probe location tracepoint. */
2165 ret = mi_lttng_writer_close_element(writer);
2166 if (ret) {
2167 goto mi_error;
2168 }
2169
2170 ret_code = LTTNG_OK;
2171 goto end;
2172
2173 mi_error:
2174 ret_code = LTTNG_ERR_MI_IO_FAIL;
2175 end:
2176 return ret_code;
2177 }
2178
2179 static enum lttng_error_code lttng_userspace_probe_location_function_mi_serialize(
2180 const struct lttng_userspace_probe_location *location,
2181 struct mi_writer *writer)
2182 {
2183 int ret;
2184 enum lttng_error_code ret_code;
2185 const char *function_name = NULL;
2186 const char *binary_path = NULL;
2187 const char *instrumentation_type_str = NULL;
2188 enum lttng_userspace_probe_location_function_instrumentation_type
2189 instrumentation_type;
2190 const struct lttng_userspace_probe_location_lookup_method
2191 *lookup_method = NULL;
2192
2193 LTTNG_ASSERT(location);
2194 LTTNG_ASSERT(writer);
2195
2196 function_name = lttng_userspace_probe_location_function_get_function_name(
2197 location);
2198 binary_path = lttng_userspace_probe_location_function_get_binary_path(
2199 location);
2200 instrumentation_type =
2201 lttng_userspace_probe_location_function_get_instrumentation_type(
2202 location);
2203 lookup_method = lttng_userspace_probe_location_function_get_lookup_method(
2204 location);
2205
2206 switch (instrumentation_type) {
2207 case LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY:
2208 instrumentation_type_str =
2209 mi_lttng_userspace_probe_location_function_instrumentation_type_entry;
2210 break;
2211 default:
2212 abort();
2213 break;
2214 }
2215
2216 /* Open userspace probe location function element. */
2217 ret = mi_lttng_writer_open_element(writer,
2218 mi_lttng_element_userspace_probe_location_function);
2219 if (ret) {
2220 goto mi_error;
2221 }
2222
2223 /* Function name. */
2224 ret = mi_lttng_writer_write_element_string(writer,
2225 mi_lttng_element_userspace_probe_location_function_name,
2226 function_name);
2227 if (ret) {
2228 goto mi_error;
2229 }
2230
2231 /* Binary path. */
2232 ret = mi_lttng_writer_write_element_string(writer,
2233 mi_lttng_element_userspace_probe_location_binary_path,
2234 binary_path);
2235 if (ret) {
2236 goto mi_error;
2237 }
2238
2239 /* Instrumentation type. */
2240 ret = mi_lttng_writer_write_element_string(writer,
2241 mi_lttng_element_userspace_probe_location_function_instrumentation_type,
2242 instrumentation_type_str);
2243 if (ret) {
2244 goto mi_error;
2245 }
2246
2247 /* The lookup method. */
2248 ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize(
2249 lookup_method, writer);
2250 if (ret_code != LTTNG_OK) {
2251 goto end;
2252 }
2253
2254 /* Close userspace probe location function element. */
2255 ret = mi_lttng_writer_close_element(writer);
2256 if (ret) {
2257 goto mi_error;
2258 }
2259
2260 ret_code = LTTNG_OK;
2261 goto end;
2262
2263 mi_error:
2264 ret_code = LTTNG_ERR_MI_IO_FAIL;
2265 end:
2266 return ret_code;
2267 }
This page took 0.107401 seconds and 5 git commands to generate.