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