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