fe11e3b5018c26d6136067e84bd1d7f7185ee17f
[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 goto end;
1221 }
1222
1223 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1224 if (!binary_path) {
1225 PERROR("lttng_strndup");
1226 goto end;
1227 }
1228
1229 *location = lttng_userspace_probe_location_function_create_no_check(
1230 binary_path, function_name, NULL, false);
1231 if (!(*location)) {
1232 ret = -LTTNG_ERR_INVALID;
1233 goto end;
1234 }
1235
1236 ret = (int) expected_size;
1237 end:
1238 free(function_name);
1239 free(binary_path);
1240 return ret;
1241 }
1242
1243 static
1244 int lttng_userspace_probe_location_tracepoint_create_from_buffer(
1245 const struct lttng_buffer_view *buffer,
1246 struct lttng_userspace_probe_location **location)
1247 {
1248 struct lttng_userspace_probe_location_tracepoint_comm *location_tracepoint_comm;
1249 const char *probe_name_src, *provider_name_src, *binary_path_src;
1250 char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
1251 int ret = 0;
1252
1253 assert(buffer);
1254 assert(buffer->data);
1255 assert(location);
1256
1257 location_tracepoint_comm =
1258 (struct lttng_userspace_probe_location_tracepoint_comm *) buffer->data;
1259
1260 const size_t expected_size = sizeof(*location_tracepoint_comm) +
1261 location_tracepoint_comm->probe_name_len +
1262 location_tracepoint_comm->provider_name_len +
1263 location_tracepoint_comm->binary_path_len;
1264
1265 if (buffer->size < expected_size) {
1266 ret = -LTTNG_ERR_INVALID;
1267 goto end;
1268 }
1269
1270 probe_name_src = buffer->data + sizeof(*location_tracepoint_comm);
1271 provider_name_src = probe_name_src +
1272 location_tracepoint_comm->probe_name_len;
1273 binary_path_src = provider_name_src +
1274 location_tracepoint_comm->provider_name_len;
1275
1276 if (probe_name_src[location_tracepoint_comm->probe_name_len - 1] != '\0') {
1277 ret = -LTTNG_ERR_INVALID;
1278 goto end;
1279 }
1280
1281 if (provider_name_src[location_tracepoint_comm->provider_name_len - 1] != '\0') {
1282 ret = -LTTNG_ERR_INVALID;
1283 goto end;
1284 }
1285
1286 if (binary_path_src[location_tracepoint_comm->binary_path_len - 1] != '\0') {
1287 ret = -LTTNG_ERR_INVALID;
1288 goto end;
1289 }
1290
1291 probe_name = lttng_strndup(probe_name_src, LTTNG_SYMBOL_NAME_LEN);
1292 if (!probe_name) {
1293 PERROR("lttng_strndup");
1294 goto end;
1295 }
1296 provider_name = lttng_strndup(provider_name_src, LTTNG_SYMBOL_NAME_LEN);
1297 if (!provider_name) {
1298 PERROR("lttng_strndup");
1299 goto end;
1300 }
1301
1302 binary_path = lttng_strndup(binary_path_src, LTTNG_SYMBOL_NAME_LEN);
1303 if (!binary_path) {
1304 PERROR("lttng_strndup");
1305 goto end;
1306 }
1307
1308 *location = lttng_userspace_probe_location_tracepoint_create_no_check(
1309 binary_path, provider_name, probe_name, NULL, false);
1310 if (!(*location)) {
1311 ret = -LTTNG_ERR_INVALID;
1312 goto end;
1313 }
1314
1315 ret = (int) expected_size;
1316 end:
1317 free(probe_name);
1318 free(provider_name);
1319 free(binary_path);
1320 return ret;
1321 }
1322
1323 static
1324 int lttng_userspace_probe_location_lookup_method_create_from_buffer(
1325 struct lttng_buffer_view *buffer,
1326 struct lttng_userspace_probe_location_lookup_method **lookup_method)
1327 {
1328 int ret;
1329 struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
1330 enum lttng_userspace_probe_location_lookup_method_type type;
1331
1332 assert(buffer);
1333 assert(buffer->data);
1334 assert(lookup_method);
1335
1336 if (buffer->size < sizeof(*lookup_comm)) {
1337 ret = -LTTNG_ERR_INVALID;
1338 goto end;
1339 }
1340
1341 lookup_comm = (struct lttng_userspace_probe_location_lookup_method_comm *)
1342 buffer->data;
1343 type = (enum lttng_userspace_probe_location_lookup_method_type)
1344 lookup_comm->type;
1345 switch (type) {
1346 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
1347 *lookup_method = NULL;
1348 break;
1349 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
1350 *lookup_method =
1351 lttng_userspace_probe_location_lookup_method_function_elf_create();
1352 if (!(*lookup_method)) {
1353 ret = -LTTNG_ERR_INVALID;
1354 goto end;
1355 }
1356 break;
1357 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
1358 *lookup_method =
1359 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1360 if (!(*lookup_method)) {
1361 ret = -LTTNG_ERR_INVALID;
1362 goto end;
1363 }
1364 break;
1365 default:
1366 ret = -LTTNG_ERR_INVALID;
1367 goto end;
1368 }
1369
1370 ret = sizeof(*lookup_comm);
1371 end:
1372 return ret;
1373 }
1374
1375 LTTNG_HIDDEN
1376 int lttng_userspace_probe_location_create_from_buffer(
1377 const struct lttng_buffer_view *buffer,
1378 struct lttng_userspace_probe_location **location)
1379 {
1380 struct lttng_userspace_probe_location_lookup_method *lookup_method;
1381 struct lttng_userspace_probe_location_comm *probe_location_comm;
1382 enum lttng_userspace_probe_location_type type;
1383 struct lttng_buffer_view lookup_method_view;
1384 int consumed = 0;
1385 int ret;
1386
1387
1388 assert(buffer);
1389 assert(buffer->data);
1390 assert(location);
1391
1392 lookup_method = NULL;
1393
1394 if (buffer->size <= sizeof(*probe_location_comm)) {
1395 ret = -LTTNG_ERR_INVALID;
1396 goto end;
1397 }
1398
1399 probe_location_comm =
1400 (struct lttng_userspace_probe_location_comm *) buffer->data;
1401 type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
1402 consumed += sizeof(*probe_location_comm);
1403
1404 switch (type) {
1405 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1406 {
1407 struct lttng_buffer_view view = lttng_buffer_view_from_view(
1408 buffer, consumed, buffer->size - consumed);
1409
1410 ret = lttng_userspace_probe_location_function_create_from_buffer(
1411 &view, location);
1412 if (ret < 0) {
1413 goto end;
1414 }
1415 break;
1416 }
1417 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1418 {
1419 struct lttng_buffer_view view = lttng_buffer_view_from_view(
1420 buffer, consumed, buffer->size - consumed);
1421
1422 ret = lttng_userspace_probe_location_tracepoint_create_from_buffer(
1423 &view, location);
1424 if (ret < 0) {
1425 goto end;
1426 }
1427 break;
1428 }
1429 default:
1430 ret = -LTTNG_ERR_INVALID;
1431 goto end;
1432 }
1433
1434 consumed += ret;
1435 if (buffer->size <= consumed) {
1436 ret = -LTTNG_ERR_INVALID;
1437 goto end;
1438 }
1439
1440 lookup_method_view = lttng_buffer_view_from_view(buffer, consumed,
1441 buffer->size - consumed);
1442 ret = lttng_userspace_probe_location_lookup_method_create_from_buffer(
1443 &lookup_method_view, &lookup_method);
1444 if (ret < 0) {
1445 ret = -LTTNG_ERR_INVALID;
1446 goto end;
1447 }
1448
1449 assert(lookup_method);
1450 (*location)->lookup_method = lookup_method;
1451 lookup_method = NULL;
1452 ret += consumed;
1453 end:
1454 return ret;
1455 }
1456
1457 LTTNG_HIDDEN
1458 int lttng_userspace_probe_location_function_set_binary_fd(
1459 struct lttng_userspace_probe_location *location, int binary_fd)
1460 {
1461 int ret = 0;
1462 struct lttng_userspace_probe_location_function *function_location;
1463
1464 assert(location);
1465 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1466
1467 function_location = container_of(location,
1468 struct lttng_userspace_probe_location_function, parent);
1469 if (function_location->binary_fd >= 0) {
1470 ret = close(function_location->binary_fd);
1471 if (ret) {
1472 PERROR("close");
1473 ret = -LTTNG_ERR_INVALID;
1474 goto end;
1475 }
1476 }
1477
1478 function_location->binary_fd = binary_fd;
1479 end:
1480 return ret;
1481 }
1482
1483 LTTNG_HIDDEN
1484 int lttng_userspace_probe_location_tracepoint_set_binary_fd(
1485 struct lttng_userspace_probe_location *location, int binary_fd)
1486 {
1487 int ret = 0;
1488 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
1489
1490 assert(location);
1491 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1492
1493 tracepoint_location = container_of(location,
1494 struct lttng_userspace_probe_location_tracepoint, parent);
1495 if (tracepoint_location->binary_fd >= 0) {
1496 ret = close(tracepoint_location->binary_fd);
1497 if (ret) {
1498 PERROR("close");
1499 ret = -LTTNG_ERR_INVALID;
1500 goto end;
1501 }
1502 }
1503
1504 tracepoint_location->binary_fd = binary_fd;
1505 end:
1506 return ret;
1507 }
1508
1509 static
1510 int lttng_userspace_probe_location_function_flatten(
1511 const struct lttng_userspace_probe_location *location,
1512 struct lttng_dynamic_buffer *buffer)
1513 {
1514 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method;
1515 struct lttng_userspace_probe_location_function *probe_function;
1516 struct lttng_userspace_probe_location_function flat_probe;
1517 size_t function_name_len, binary_path_len;
1518 size_t padding_needed = 0;
1519 char *flat_probe_start;
1520 int storage_needed = 0;
1521 int ret;
1522
1523 assert(location);
1524
1525 if (location->lookup_method && location->lookup_method->type !=
1526 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF) {
1527 ret = -LTTNG_ERR_INVALID;
1528 goto end;
1529 }
1530
1531 probe_function = container_of(location,
1532 struct lttng_userspace_probe_location_function,
1533 parent);
1534 assert(probe_function->function_name);
1535 assert(probe_function->binary_path);
1536
1537 storage_needed +=
1538 sizeof(struct lttng_userspace_probe_location_function);
1539 function_name_len = strlen(probe_function->function_name) + 1;
1540 binary_path_len = strlen(probe_function->binary_path) + 1;
1541 storage_needed += function_name_len + binary_path_len;
1542
1543 /*
1544 * The lookup method is aligned to 64-bit within the buffer.
1545 * This is needed even if there is no lookup method since
1546 * the next structure in the buffer probably needs to be
1547 * aligned too (depending on the arch).
1548 */
1549 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1550 storage_needed += padding_needed;
1551
1552 if (location->lookup_method) {
1553 /* NOTE: elf look-up method is assumed here. */
1554 storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1555 }
1556
1557 if (!buffer) {
1558 ret = storage_needed;
1559 goto end;
1560 }
1561
1562 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1563 ret = lttng_dynamic_buffer_set_capacity(buffer,
1564 buffer->size + storage_needed);
1565 if (ret) {
1566 goto end;
1567 }
1568 }
1569
1570 memset(&flat_probe, 0, sizeof(flat_probe));
1571
1572 flat_probe_start = buffer->data + buffer->size;
1573 flat_probe.parent.type = location->type;
1574 /*
1575 * The lookup method, if present, is the last element in the flat
1576 * representation of the probe.
1577 */
1578 if (location->lookup_method) {
1579 flat_probe.parent.lookup_method =
1580 (struct lttng_userspace_probe_location_lookup_method *)
1581 (flat_probe_start + sizeof(flat_probe) +
1582 function_name_len + binary_path_len + padding_needed);
1583 } else {
1584 flat_probe.parent.lookup_method = NULL;
1585 }
1586
1587 flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
1588 flat_probe.binary_path = flat_probe.function_name + function_name_len;
1589 flat_probe.binary_fd = -1;
1590 ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
1591 sizeof(flat_probe));
1592 if (ret) {
1593 goto end;
1594 }
1595
1596 ret = lttng_dynamic_buffer_append(buffer,
1597 probe_function->function_name, function_name_len);
1598 if (ret) {
1599 goto end;
1600 }
1601 ret = lttng_dynamic_buffer_append(buffer,
1602 probe_function->binary_path, binary_path_len);
1603 if (ret) {
1604 goto end;
1605 }
1606
1607 /* Insert padding before the lookup method. */
1608 ret = lttng_dynamic_buffer_set_size(buffer,
1609 buffer->size + padding_needed);
1610 if (ret) {
1611 goto end;
1612 }
1613
1614 if (!location->lookup_method) {
1615 /* Not an error, the default method is used. */
1616 ret = storage_needed;
1617 goto end;
1618 }
1619
1620 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1621 flat_lookup_method.parent.type =
1622 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
1623 ret = lttng_dynamic_buffer_append(buffer,
1624 &flat_lookup_method, sizeof(flat_lookup_method));
1625 if (ret) {
1626 goto end;
1627 }
1628 ret = storage_needed;
1629 end:
1630 return ret;
1631 }
1632
1633 static
1634 int lttng_userspace_probe_location_tracepoint_flatten(
1635 const struct lttng_userspace_probe_location *location,
1636 struct lttng_dynamic_buffer *buffer)
1637 {
1638 struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method;
1639 struct lttng_userspace_probe_location_tracepoint *probe_tracepoint;
1640 struct lttng_userspace_probe_location_tracepoint flat_probe;
1641 size_t probe_name_len, provider_name_len, binary_path_len;
1642 size_t padding_needed = 0;
1643 int storage_needed = 0;
1644 char *flat_probe_start;
1645 int ret = 0;
1646
1647 assert(location);
1648
1649 /* Only SDT tracepoints are supported at the moment */
1650 if (location->lookup_method && location->lookup_method->type !=
1651 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT) {
1652 ret = -LTTNG_ERR_INVALID;
1653 goto end;
1654 }
1655 probe_tracepoint = container_of(location,
1656 struct lttng_userspace_probe_location_tracepoint,
1657 parent);
1658 assert(probe_tracepoint->probe_name);
1659 assert(probe_tracepoint->provider_name);
1660 assert(probe_tracepoint->binary_path);
1661
1662 /* Compute the storage space needed to flatten the probe location */
1663 storage_needed += sizeof(struct lttng_userspace_probe_location_tracepoint);
1664
1665 probe_name_len = strlen(probe_tracepoint->probe_name) + 1;
1666 provider_name_len = strlen(probe_tracepoint->provider_name) + 1;
1667 binary_path_len = strlen(probe_tracepoint->binary_path) + 1;
1668
1669 storage_needed += probe_name_len + provider_name_len + binary_path_len;
1670
1671 /*
1672 * The lookup method is aligned to 64-bit within the buffer.
1673 * This is needed even if there is no lookup method since
1674 * the next structure in the buffer probably needs to be
1675 * aligned too (depending on the arch).
1676 */
1677 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1678 storage_needed += padding_needed;
1679
1680 if (location->lookup_method) {
1681 /* NOTE: elf look-up method is assumed here. */
1682 storage_needed +=
1683 sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1684 }
1685
1686 /*
1687 * If the caller set buffer to NULL, return the size of the needed buffer.
1688 */
1689 if (!buffer) {
1690 ret = storage_needed;
1691 goto end;
1692 }
1693
1694 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1695 ret = lttng_dynamic_buffer_set_capacity(buffer,
1696 buffer->size + storage_needed);
1697 if (ret) {
1698 goto end;
1699 }
1700 }
1701
1702 memset(&flat_probe, 0, sizeof(flat_probe));
1703
1704 flat_probe_start = buffer->data + buffer->size;
1705 flat_probe.parent.type = location->type;
1706
1707 /*
1708 * The lookup method, if present, is the last element in the flat
1709 * representation of the probe.
1710 */
1711 if (location->lookup_method) {
1712 flat_probe.parent.lookup_method =
1713 (struct lttng_userspace_probe_location_lookup_method *)
1714 (flat_probe_start + sizeof(flat_probe) +
1715 probe_name_len + provider_name_len +
1716 binary_path_len + padding_needed);
1717 } else {
1718 flat_probe.parent.lookup_method = NULL;
1719 }
1720
1721 flat_probe.probe_name = flat_probe_start + sizeof(flat_probe);
1722 flat_probe.provider_name = flat_probe.probe_name + probe_name_len;
1723 flat_probe.binary_path = flat_probe.provider_name + provider_name_len;
1724 flat_probe.binary_fd = -1;
1725 ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe));
1726 if (ret) {
1727 goto end;
1728 }
1729
1730 /* Append all the fields to the buffer */
1731 ret = lttng_dynamic_buffer_append(buffer,
1732 probe_tracepoint->probe_name, probe_name_len);
1733 if (ret) {
1734 goto end;
1735 }
1736 ret = lttng_dynamic_buffer_append(buffer,
1737 probe_tracepoint->provider_name, provider_name_len);
1738 if (ret) {
1739 goto end;
1740 }
1741 ret = lttng_dynamic_buffer_append(buffer,
1742 probe_tracepoint->binary_path, binary_path_len);
1743 if (ret) {
1744 goto end;
1745 }
1746
1747 /* Insert padding before the lookup method. */
1748 ret = lttng_dynamic_buffer_set_size(buffer, buffer->size + padding_needed);
1749 if (ret) {
1750 goto end;
1751 }
1752
1753 if (!location->lookup_method) {
1754 /* Not an error, the default method is used. */
1755 ret = storage_needed;
1756 goto end;
1757 }
1758
1759 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1760
1761 flat_lookup_method.parent.type =
1762 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
1763 ret = lttng_dynamic_buffer_append(buffer,
1764 &flat_lookup_method, sizeof(flat_lookup_method));
1765 if (ret) {
1766 goto end;
1767 }
1768 ret = storage_needed;
1769 end:
1770 return ret;
1771 }
1772
1773 LTTNG_HIDDEN
1774 int lttng_userspace_probe_location_flatten(
1775 const struct lttng_userspace_probe_location *location,
1776 struct lttng_dynamic_buffer *buffer)
1777 {
1778 int ret;
1779 if (!location) {
1780 ret = -LTTNG_ERR_INVALID;
1781 goto end;
1782 }
1783
1784 /* Only types currently supported. */
1785 switch (location->type) {
1786 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1787 ret = lttng_userspace_probe_location_function_flatten(location, buffer);
1788 break;
1789 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1790 ret = lttng_userspace_probe_location_tracepoint_flatten(location, buffer);
1791 break;
1792 default:
1793 ret = -LTTNG_ERR_INVALID;
1794 goto end;
1795 }
1796
1797 end:
1798 return ret;
1799 }
1800
1801 LTTNG_HIDDEN
1802 struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
1803 const struct lttng_userspace_probe_location *location)
1804 {
1805 struct lttng_userspace_probe_location *new_location = NULL;
1806 enum lttng_userspace_probe_location_type type;
1807
1808 if (!location) {
1809 goto err;
1810 }
1811
1812 type = lttng_userspace_probe_location_get_type(location);
1813 switch (type) {
1814 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1815 new_location =
1816 lttng_userspace_probe_location_function_copy(location);
1817 if (!new_location) {
1818 goto err;
1819 }
1820 break;
1821 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1822 new_location =
1823 lttng_userspace_probe_location_tracepoint_copy(location);
1824 if (!new_location) {
1825 goto err;
1826 }
1827 break;
1828 default:
1829 new_location = NULL;
1830 goto err;
1831 }
1832 err:
1833 return new_location;
1834 }
1835
1836 LTTNG_HIDDEN
1837 bool lttng_userspace_probe_location_lookup_method_is_equal(
1838 const struct lttng_userspace_probe_location_lookup_method *a,
1839 const struct lttng_userspace_probe_location_lookup_method *b)
1840 {
1841 bool is_equal = false;
1842
1843 if (!a || !b) {
1844 goto end;
1845 }
1846
1847 if (a == b) {
1848 is_equal = true;
1849 goto end;
1850 }
1851
1852 if (a->type != b->type) {
1853 goto end;
1854 }
1855
1856 is_equal = true;
1857 end:
1858 return is_equal;
1859 }
1860
1861 LTTNG_HIDDEN
1862 bool lttng_userspace_probe_location_is_equal(
1863 const struct lttng_userspace_probe_location *a,
1864 const struct lttng_userspace_probe_location *b)
1865 {
1866 bool is_equal = false;
1867
1868 if (!a || !b) {
1869 goto end;
1870 }
1871
1872 if (a == b) {
1873 is_equal = true;
1874 goto end;
1875 }
1876
1877 if (!lttng_userspace_probe_location_lookup_method_is_equal(
1878 a->lookup_method, b->lookup_method)) {
1879 goto end;
1880 }
1881
1882 if (a->type != b->type) {
1883 goto end;
1884 }
1885
1886 is_equal = a->equal ? a->equal(a, b) : true;
1887 end:
1888 return is_equal;
1889 }
This page took 0.116617 seconds and 4 git commands to generate.