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