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