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