SoW-2019-0007-2: Dynamic Snapshot: Triggers send partial event payload with notifications
[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 /*
151 * Compare two FDs.
152 * For now only the Inode number is compared.
153 */
154 static bool fd_is_equal(int a, int b)
155 {
156 int ret;
157 bool is_equal = false;
158 struct stat a_stat, b_stat;
159
160 if (a < 0 && b >= 0) {
161 goto end;
162 }
163
164 if (b < 0 && a >= 0) {
165 goto end;
166 }
167
168 if (a < 0 && b < 0) {
169 if (a == -1 && b == -1) {
170 is_equal = true;
171 goto end;
172 }
173 /* Invalid state, assert */
174 assert(0);
175 goto end;
176 }
177
178 /* Both are valid FD numbers */
179 ret = fstat(a, &a_stat);
180 if (ret) {
181 PERROR("fstat on fd a: %d", a);
182 goto end;
183 }
184
185 ret = fstat(b, &b_stat);
186 if (ret) {
187 PERROR("fstat on fd b: %d", b);
188 goto end;
189 }
190
191 is_equal = (a_stat.st_ino == b_stat.st_ino);
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 // TODO: see gerrit comment: https://review.lttng.org/c/lttng-tools/+/2924/27/src/common/userspace-probe.c#255
226 //is_equal = fd_is_equal(a->binary_fd, b->binary_fd);
227 is_equal = true;
228 end:
229 return is_equal;
230 }
231
232 static struct lttng_userspace_probe_location *
233 lttng_userspace_probe_location_function_create_no_check(const char *binary_path,
234 const char *function_name,
235 struct lttng_userspace_probe_location_lookup_method *lookup_method,
236 bool open_binary)
237 {
238 int binary_fd = -1;
239 char *function_name_copy = NULL, *binary_path_copy = NULL;
240 struct lttng_userspace_probe_location *ret = NULL;
241 struct lttng_userspace_probe_location_function *location;
242
243 if (open_binary) {
244 binary_fd = open(binary_path, O_RDONLY);
245 if (binary_fd < 0) {
246 PERROR("Error opening the binary");
247 goto error;
248 }
249 } else {
250 binary_fd = -1;
251 }
252
253 function_name_copy = lttng_strndup(function_name, LTTNG_SYMBOL_NAME_LEN);
254 if (!function_name_copy) {
255 PERROR("Error duplicating the function name");
256 goto error;
257 }
258
259 binary_path_copy = lttng_strndup(binary_path, LTTNG_PATH_MAX);
260 if (!binary_path_copy) {
261 PERROR("Error duplicating the function name");
262 goto error;
263 }
264
265 location = zmalloc(sizeof(*location));
266 if (!location) {
267 PERROR("Error allocating userspace probe location");
268 goto error;
269 }
270
271 location->function_name = function_name_copy;
272 location->binary_path = binary_path_copy;
273 location->binary_fd = binary_fd;
274 location->instrumentation_type =
275 LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY;
276
277 ret = &location->parent;
278 ret->lookup_method = lookup_method;
279 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION;
280 ret->equal = lttng_userspace_probe_location_function_is_equal;
281 goto end;
282
283 error:
284 free(function_name_copy);
285 free(binary_path_copy);
286 if (binary_fd >= 0) {
287 if (close(binary_fd)) {
288 PERROR("Error closing binary fd in error path");
289 }
290 }
291 end:
292 return ret;
293 }
294
295 static bool lttng_userspace_probe_location_tracepoint_is_equal(
296 const struct lttng_userspace_probe_location *_a,
297 const struct lttng_userspace_probe_location *_b)
298 {
299 bool is_equal = false;
300 struct lttng_userspace_probe_location_tracepoint *a, *b;
301
302 a = container_of(_a, struct lttng_userspace_probe_location_tracepoint,
303 parent);
304 b = container_of(_b, struct lttng_userspace_probe_location_tracepoint,
305 parent);
306
307 assert(a->probe_name);
308 assert(b->probe_name);
309 if (strcmp(a->probe_name, b->probe_name)) {
310 goto end;
311 }
312
313 assert(a->provider_name);
314 assert(b->provider_name);
315 if (strcmp(a->provider_name, b->provider_name)) {
316 goto end;
317 }
318
319 assert(a->binary_path);
320 assert(b->binary_path);
321 if (strcmp(a->binary_path, b->binary_path)) {
322 goto end;
323 }
324
325 is_equal = fd_is_equal(a->binary_fd, b->binary_fd);
326
327 end:
328 return is_equal;
329 }
330
331 static struct lttng_userspace_probe_location *
332 lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_path,
333 const char *provider_name, const char *probe_name,
334 struct lttng_userspace_probe_location_lookup_method *lookup_method,
335 bool open_binary)
336 {
337 int binary_fd = -1;
338 char *probe_name_copy = NULL;
339 char *provider_name_copy = NULL;
340 char *binary_path_copy = NULL;
341 struct lttng_userspace_probe_location *ret = NULL;
342 struct lttng_userspace_probe_location_tracepoint *location;
343
344 if (open_binary) {
345 binary_fd = open(binary_path, O_RDONLY);
346 if (binary_fd < 0) {
347 PERROR("open");
348 goto error;
349 }
350 } else {
351 binary_fd = -1;
352 }
353
354 probe_name_copy = lttng_strndup(probe_name, LTTNG_SYMBOL_NAME_LEN);
355 if (!probe_name_copy) {
356 PERROR("lttng_strndup");
357 goto error;
358 }
359
360 provider_name_copy = lttng_strndup(provider_name, LTTNG_SYMBOL_NAME_LEN);
361 if (!provider_name_copy) {
362 PERROR("lttng_strndup");
363 goto error;
364 }
365
366 binary_path_copy = lttng_strndup(binary_path, LTTNG_PATH_MAX);
367 if (!binary_path_copy) {
368 PERROR("lttng_strndup");
369 goto error;
370 }
371
372 location = zmalloc(sizeof(*location));
373 if (!location) {
374 PERROR("zmalloc");
375 goto error;
376 }
377
378 location->probe_name = probe_name_copy;
379 location->provider_name = provider_name_copy;
380 location->binary_path = binary_path_copy;
381 location->binary_fd = binary_fd;
382
383 ret = &location->parent;
384 ret->lookup_method = lookup_method;
385 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT;
386 ret->equal = lttng_userspace_probe_location_tracepoint_is_equal;
387 goto end;
388
389 error:
390 free(probe_name_copy);
391 free(provider_name_copy);
392 free(binary_path_copy);
393 if (binary_fd >= 0) {
394 if (close(binary_fd)) {
395 PERROR("Error closing binary fd in error path");
396 }
397 }
398 end:
399 return ret;
400 }
401
402 struct lttng_userspace_probe_location *
403 lttng_userspace_probe_location_function_create(const char *binary_path,
404 const char *function_name,
405 struct lttng_userspace_probe_location_lookup_method *lookup_method)
406 {
407 struct lttng_userspace_probe_location *ret = NULL;
408
409 if (!binary_path || !function_name) {
410 ERR("Invalid argument(s)");
411 goto end;
412 }
413
414 switch (lttng_userspace_probe_location_lookup_method_get_type(
415 lookup_method)) {
416 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
417 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
418 break;
419 default:
420 /* Invalid probe location lookup method. */
421 goto end;
422 }
423
424 ret = lttng_userspace_probe_location_function_create_no_check(
425 binary_path, function_name, lookup_method, true);
426 end:
427 return ret;
428 }
429
430 struct lttng_userspace_probe_location *
431 lttng_userspace_probe_location_tracepoint_create(const char *binary_path,
432 const char *provider_name, const char *probe_name,
433 struct lttng_userspace_probe_location_lookup_method *lookup_method)
434 {
435 struct lttng_userspace_probe_location *ret = NULL;
436
437 if (!binary_path || !probe_name || !provider_name) {
438 ERR("Invalid argument(s)");
439 goto end;
440 }
441
442 switch (lttng_userspace_probe_location_lookup_method_get_type(
443 lookup_method)) {
444 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
445 break;
446 default:
447 /* Invalid probe location lookup method. */
448 goto end;
449 }
450
451 ret = lttng_userspace_probe_location_tracepoint_create_no_check(
452 binary_path, provider_name, probe_name, lookup_method, true);
453 end:
454 return ret;
455 }
456
457 static struct lttng_userspace_probe_location_lookup_method *
458 lttng_userspace_probe_location_lookup_method_function_elf_copy(
459 const struct lttng_userspace_probe_location_lookup_method *lookup_method)
460 {
461 struct lttng_userspace_probe_location_lookup_method *parent = NULL;
462 struct lttng_userspace_probe_location_lookup_method_elf *elf_method;
463
464 assert(lookup_method);
465 assert(lookup_method->type ==
466 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF);
467
468 elf_method = zmalloc(sizeof(*elf_method));
469 if (!elf_method) {
470 PERROR("Error allocating ELF userspace probe lookup method");
471 goto error;
472 }
473
474 elf_method->parent.type = lookup_method->type;
475 parent = &elf_method->parent;
476
477 goto end;
478 error:
479 parent = NULL;
480 end:
481 return parent;
482 }
483
484 static struct lttng_userspace_probe_location_lookup_method *
485 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
486 struct lttng_userspace_probe_location_lookup_method *lookup_method)
487 {
488 struct lttng_userspace_probe_location_lookup_method *parent = NULL;
489 struct lttng_userspace_probe_location_lookup_method_sdt *sdt_method;
490
491 assert(lookup_method);
492 assert(lookup_method->type ==
493 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT);
494
495 sdt_method = zmalloc(sizeof(*sdt_method));
496 if (!sdt_method) {
497 PERROR("zmalloc");
498 goto error;
499 }
500
501 sdt_method->parent.type = lookup_method->type;
502 parent = &sdt_method->parent;
503
504 goto end;
505
506 error:
507 parent = NULL;
508 end:
509 return parent;
510 }
511
512 static struct lttng_userspace_probe_location *
513 lttng_userspace_probe_location_function_copy(
514 const struct lttng_userspace_probe_location *location)
515 {
516 enum lttng_userspace_probe_location_lookup_method_type lookup_type;
517 struct lttng_userspace_probe_location *new_location = NULL;
518 struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
519 const char *binary_path = NULL;
520 const char *function_name = NULL;
521 int fd, new_fd;
522
523 assert(location);
524 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
525
526 /* Get probe location fields */
527 binary_path = lttng_userspace_probe_location_function_get_binary_path(location);
528 if (!binary_path) {
529 ERR("Userspace probe binary path is NULL");
530 goto error;
531 }
532
533 function_name = lttng_userspace_probe_location_function_get_function_name(location);
534 if (!function_name) {
535 ERR("Userspace probe function name is NULL");
536 goto error;
537 }
538
539 /* Duplicate the binary fd */
540 fd = lttng_userspace_probe_location_function_get_binary_fd(location);
541 if (fd == -1) {
542 ERR("Error getting file descriptor to binary");
543 goto error;
544 }
545
546 new_fd = dup(fd);
547 if (new_fd == -1) {
548 PERROR("Error duplicating file descriptor to binary");
549 goto error;
550 }
551
552 /*
553 * Duplicate probe location method fields
554 */
555 lookup_type = lttng_userspace_probe_location_lookup_method_get_type(
556 location->lookup_method);
557 switch (lookup_type) {
558 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
559 lookup_method =
560 lttng_userspace_probe_location_lookup_method_function_elf_copy(
561 location->lookup_method);
562 if (!lookup_method) {
563 goto close_fd;
564 }
565 break;
566 default:
567 /* Invalid probe location lookup method. */
568 goto close_fd;
569 }
570
571 /* Create the probe_location */
572 new_location = lttng_userspace_probe_location_function_create_no_check(
573 binary_path, function_name, lookup_method, false);
574 if (!new_location) {
575 goto destroy_lookup_method;
576 }
577
578 /* Set the duplicated fd to the new probe_location */
579 if (lttng_userspace_probe_location_function_set_binary_fd(new_location, new_fd) < 0) {
580 goto destroy_probe_location;
581 }
582
583 goto end;
584
585 destroy_probe_location:
586 lttng_userspace_probe_location_destroy(new_location);
587 destroy_lookup_method:
588 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
589 close_fd:
590 if (close(new_fd) < 0) {
591 PERROR("Error closing duplicated file descriptor in error path");
592 }
593 error:
594 new_location = NULL;
595 end:
596 return new_location;
597 }
598
599 static struct lttng_userspace_probe_location *
600 lttng_userspace_probe_location_tracepoint_copy(
601 const struct lttng_userspace_probe_location *location)
602 {
603 enum lttng_userspace_probe_location_lookup_method_type lookup_type;
604 struct lttng_userspace_probe_location *new_location = NULL;
605 struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
606 const char *binary_path = NULL;
607 const char *probe_name = NULL;
608 const char *provider_name = NULL;
609 int fd, new_fd;
610
611 assert(location);
612 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
613
614 /* Get probe location fields */
615 binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(location);
616 if (!binary_path) {
617 ERR("Userspace probe binary path is NULL");
618 goto error;
619 }
620
621 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(location);
622 if (!probe_name) {
623 ERR("Userspace probe probe name is NULL");
624 goto error;
625 }
626
627 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(location);
628 if (!provider_name) {
629 ERR("Userspace probe provider name is NULL");
630 goto error;
631 }
632
633 /* Duplicate the binary fd */
634 fd = lttng_userspace_probe_location_tracepoint_get_binary_fd(location);
635 if (fd == -1) {
636 ERR("Error getting file descriptor to binary");
637 goto error;
638 }
639
640 new_fd = dup(fd);
641 if (new_fd == -1) {
642 PERROR("Error duplicating file descriptor to binary");
643 goto error;
644 }
645
646 /*
647 * Duplicate probe location method fields
648 */
649 lookup_type = lttng_userspace_probe_location_lookup_method_get_type(
650 location->lookup_method);
651 switch (lookup_type) {
652 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
653 lookup_method =
654 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
655 location->lookup_method);
656 if (!lookup_method) {
657 goto close_fd;
658 }
659 break;
660 default:
661 /* Invalid probe location lookup method. */
662 goto close_fd;
663 }
664
665 /* Create the probe_location */
666 new_location = lttng_userspace_probe_location_tracepoint_create_no_check(
667 binary_path, provider_name, probe_name, lookup_method, false);
668 if (!new_location) {
669 goto destroy_lookup_method;
670 }
671
672 /* Set the duplicated fd to the new probe_location */
673 if (lttng_userspace_probe_location_tracepoint_set_binary_fd(new_location, new_fd) < 0) {
674 goto destroy_probe_location;
675 }
676
677 goto end;
678
679 destroy_probe_location:
680 lttng_userspace_probe_location_destroy(new_location);
681 destroy_lookup_method:
682 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
683 close_fd:
684 if (close(new_fd) < 0) {
685 PERROR("Error closing duplicated file descriptor in error path");
686 }
687 error:
688 new_location = NULL;
689 end:
690 return new_location;
691 }
692
693 const char *lttng_userspace_probe_location_function_get_binary_path(
694 const struct lttng_userspace_probe_location *location)
695 {
696 const char *ret = NULL;
697 struct lttng_userspace_probe_location_function *function_location;
698
699 if (!location || lttng_userspace_probe_location_get_type(location) !=
700 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
701 ERR("Invalid argument(s)");
702 goto end;
703 }
704
705 function_location = container_of(location,
706 struct lttng_userspace_probe_location_function,
707 parent);
708 ret = function_location->binary_path;
709 end:
710 return ret;
711 }
712
713 const char *lttng_userspace_probe_location_tracepoint_get_binary_path(
714 const struct lttng_userspace_probe_location *location)
715 {
716 const char *ret = NULL;
717 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
718
719 if (!location || lttng_userspace_probe_location_get_type(location) !=
720 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
721 ERR("Invalid argument(s)");
722 goto end;
723 }
724
725 tracepoint_location = container_of(location,
726 struct lttng_userspace_probe_location_tracepoint,
727 parent);
728 ret = tracepoint_location->binary_path;
729 end:
730 return ret;
731 }
732
733 const char *lttng_userspace_probe_location_function_get_function_name(
734 const struct lttng_userspace_probe_location *location)
735 {
736 const char *ret = NULL;
737 struct lttng_userspace_probe_location_function *function_location;
738
739 if (!location || lttng_userspace_probe_location_get_type(location) !=
740 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
741 ERR("Invalid argument(s)");
742 goto end;
743 }
744
745 function_location = container_of(location,
746 struct lttng_userspace_probe_location_function, parent);
747 ret = function_location->function_name;
748 end:
749 return ret;
750 }
751
752 const char *lttng_userspace_probe_location_tracepoint_get_probe_name(
753 const struct lttng_userspace_probe_location *location)
754 {
755 const char *ret = NULL;
756 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
757
758 if (!location || lttng_userspace_probe_location_get_type(location) !=
759 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
760 ERR("Invalid argument(s)");
761 goto end;
762 }
763
764 tracepoint_location = container_of(location,
765 struct lttng_userspace_probe_location_tracepoint, parent);
766 ret = tracepoint_location->probe_name;
767 end:
768 return ret;
769 }
770
771 const char *lttng_userspace_probe_location_tracepoint_get_provider_name(
772 const struct lttng_userspace_probe_location *location)
773 {
774 const char *ret = NULL;
775 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
776
777 if (!location || lttng_userspace_probe_location_get_type(location) !=
778 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
779 ERR("Invalid argument(s)");
780 goto end;
781 }
782
783 tracepoint_location = container_of(location,
784 struct lttng_userspace_probe_location_tracepoint, parent);
785 ret = tracepoint_location->provider_name;
786 end:
787 return ret;
788 }
789
790 int lttng_userspace_probe_location_function_get_binary_fd(
791 const struct lttng_userspace_probe_location *location)
792 {
793 int ret = -1;
794 struct lttng_userspace_probe_location_function *function_location;
795
796 if (!location || lttng_userspace_probe_location_get_type(location) !=
797 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
798 ERR("Invalid argument(s)");
799 goto end;
800 }
801
802 function_location = container_of(location,
803 struct lttng_userspace_probe_location_function, parent);
804 ret = function_location->binary_fd;
805 end:
806 return ret;
807 }
808
809 enum lttng_userspace_probe_location_function_instrumentation_type
810 lttng_userspace_probe_location_function_get_instrumentation_type(
811 const struct lttng_userspace_probe_location *location)
812 {
813 enum lttng_userspace_probe_location_function_instrumentation_type type;
814 struct lttng_userspace_probe_location_function *function_location;
815
816 if (!location || lttng_userspace_probe_location_get_type(location) !=
817 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
818 ERR("Invalid argument(s)");
819 type = LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_UNKNOWN;
820 goto end;
821 }
822
823 function_location = container_of(location,
824 struct lttng_userspace_probe_location_function, parent);
825 type = function_location->instrumentation_type;
826 end:
827 return type;
828 }
829
830 enum lttng_userspace_probe_location_status
831 lttng_userspace_probe_location_function_set_instrumentation_type(
832 const struct lttng_userspace_probe_location *location,
833 enum lttng_userspace_probe_location_function_instrumentation_type instrumentation_type)
834 {
835 enum lttng_userspace_probe_location_status status =
836 LTTNG_USERSPACE_PROBE_LOCATION_STATUS_OK;
837 struct lttng_userspace_probe_location_function *function_location;
838
839 if (!location || lttng_userspace_probe_location_get_type(location) !=
840 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION ||
841 instrumentation_type !=
842 LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY) {
843 ERR("Invalid argument(s)");
844 status = LTTNG_USERSPACE_PROBE_LOCATION_STATUS_INVALID;
845 goto end;
846 }
847
848 function_location = container_of(location,
849 struct lttng_userspace_probe_location_function, parent);
850 function_location->instrumentation_type = instrumentation_type;
851 end:
852 return status;
853 }
854
855 int lttng_userspace_probe_location_tracepoint_get_binary_fd(
856 const struct lttng_userspace_probe_location *location)
857 {
858 int ret = -1;
859 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
860
861 if (!location || lttng_userspace_probe_location_get_type(location) !=
862 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
863 ERR("Invalid argument(s)");
864 goto end;
865 }
866
867 tracepoint_location = container_of(location,
868 struct lttng_userspace_probe_location_tracepoint, parent);
869 ret = tracepoint_location->binary_fd;
870 end:
871 return ret;
872 }
873
874 static struct lttng_userspace_probe_location_lookup_method *
875 lttng_userspace_probe_location_function_get_lookup_method(
876 const struct lttng_userspace_probe_location *location)
877 {
878 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
879
880 if (!location || lttng_userspace_probe_location_get_type(location) !=
881 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
882 ERR("Invalid argument(s)");
883 goto end;
884 }
885
886 ret = location->lookup_method;
887 end:
888 return ret;
889 }
890
891 static struct lttng_userspace_probe_location_lookup_method *
892 lttng_userspace_probe_location_tracepoint_get_lookup_method(
893 const struct lttng_userspace_probe_location *location)
894 {
895 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
896
897 if (!location || lttng_userspace_probe_location_get_type(location) !=
898 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
899 ERR("Invalid argument(s)");
900 goto end;
901 }
902
903 ret = location->lookup_method;
904 end:
905 return ret;
906 }
907
908 const struct lttng_userspace_probe_location_lookup_method *
909 lttng_userspace_probe_location_get_lookup_method(
910 const struct lttng_userspace_probe_location *location)
911 {
912 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
913
914 assert(location);
915 switch (location->type) {
916 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
917 ret = lttng_userspace_probe_location_function_get_lookup_method(
918 location);
919 break;
920 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
921 ret = lttng_userspace_probe_location_tracepoint_get_lookup_method(
922 location);
923 break;
924 default:
925 ERR("Unknowned lookup method.");
926 break;
927 }
928 return ret;
929 }
930
931 static
932 int lttng_userspace_probe_location_lookup_method_serialize(
933 struct lttng_userspace_probe_location_lookup_method *method,
934 struct lttng_dynamic_buffer *buffer)
935 {
936 int ret;
937 struct lttng_userspace_probe_location_lookup_method_comm
938 lookup_method_comm;
939
940 lookup_method_comm.type = (int8_t) (method ? method->type :
941 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT);
942 if (buffer) {
943 ret = lttng_dynamic_buffer_append(buffer, &lookup_method_comm,
944 sizeof(lookup_method_comm));
945 if (ret) {
946 goto end;
947 }
948 }
949 ret = sizeof(lookup_method_comm);
950 end:
951 return ret;
952 }
953
954 static
955 int lttng_userspace_probe_location_function_serialize(
956 const struct lttng_userspace_probe_location *location,
957 struct lttng_dynamic_buffer *buffer,
958 int *binary_fd)
959 {
960 int ret;
961 size_t function_name_len, binary_path_len;
962 struct lttng_userspace_probe_location_function *location_function;
963 struct lttng_userspace_probe_location_function_comm location_function_comm;
964
965 assert(location);
966 assert(lttng_userspace_probe_location_get_type(location) ==
967 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
968
969 location_function = container_of(location,
970 struct lttng_userspace_probe_location_function,
971 parent);
972 if (!location_function->function_name || !location_function->binary_path) {
973 ret = -LTTNG_ERR_INVALID;
974 goto end;
975 }
976
977 if (binary_fd && location_function->binary_fd < 0) {
978 ret = -LTTNG_ERR_INVALID;
979 goto end;
980 }
981
982 if (binary_fd) {
983 *binary_fd = location_function->binary_fd;
984 }
985
986 function_name_len = strlen(location_function->function_name);
987 if (function_name_len == 0) {
988 ret = -LTTNG_ERR_INVALID;
989 goto end;
990 }
991 binary_path_len = strlen(location_function->binary_path);
992 if (binary_path_len == 0) {
993 ret = -LTTNG_ERR_INVALID;
994 goto end;
995 }
996
997 location_function_comm.function_name_len = function_name_len + 1;
998 location_function_comm.binary_path_len = binary_path_len + 1;
999
1000 if (buffer) {
1001 ret = lttng_dynamic_buffer_append(buffer,
1002 &location_function_comm,
1003 sizeof(location_function_comm));
1004 if (ret) {
1005 ret = -LTTNG_ERR_INVALID;
1006 goto end;
1007 }
1008 ret = lttng_dynamic_buffer_append(buffer,
1009 location_function->function_name,
1010 location_function_comm.function_name_len);
1011 if (ret) {
1012 ret = -LTTNG_ERR_INVALID;
1013 goto end;
1014 }
1015 ret = lttng_dynamic_buffer_append(buffer,
1016 location_function->binary_path,
1017 location_function_comm.binary_path_len);
1018 if (ret) {
1019 ret = -LTTNG_ERR_INVALID;
1020 goto end;
1021 }
1022 }
1023 ret = sizeof(location_function_comm) +
1024 location_function_comm.function_name_len +
1025 location_function_comm.binary_path_len;
1026 end:
1027 return ret;
1028 }
1029
1030 static
1031 int lttng_userspace_probe_location_tracepoint_serialize(
1032 const struct lttng_userspace_probe_location *location,
1033 struct lttng_dynamic_buffer *buffer,
1034 int *binary_fd)
1035 {
1036 int ret;
1037 size_t probe_name_len, provider_name_len, binary_path_len;
1038 struct lttng_userspace_probe_location_tracepoint *location_tracepoint;
1039 struct lttng_userspace_probe_location_tracepoint_comm location_tracepoint_comm;
1040
1041 assert(location);
1042 assert(lttng_userspace_probe_location_get_type(location) ==
1043 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1044
1045 location_tracepoint = container_of(location,
1046 struct lttng_userspace_probe_location_tracepoint,
1047 parent);
1048 if (!location_tracepoint->probe_name ||
1049 !location_tracepoint->provider_name ||
1050 !location_tracepoint->binary_path) {
1051 ret = -LTTNG_ERR_INVALID;
1052 goto end;
1053 }
1054
1055 if (binary_fd && location_tracepoint->binary_fd < 0) {
1056 ret = -LTTNG_ERR_INVALID;
1057 goto end;
1058 }
1059
1060 if (binary_fd) {
1061 *binary_fd = location_tracepoint->binary_fd;
1062 }
1063
1064 probe_name_len = strlen(location_tracepoint->probe_name);
1065 if (probe_name_len == 0) {
1066 ret = -LTTNG_ERR_INVALID;
1067 goto end;
1068 }
1069
1070 provider_name_len = strlen(location_tracepoint->provider_name);
1071 if (provider_name_len == 0) {
1072 ret = -LTTNG_ERR_INVALID;
1073 goto end;
1074 }
1075
1076 binary_path_len = strlen(location_tracepoint->binary_path);
1077 if (binary_path_len == 0) {
1078 ret = -LTTNG_ERR_INVALID;
1079 goto end;
1080 }
1081
1082 location_tracepoint_comm.probe_name_len = probe_name_len + 1;
1083 location_tracepoint_comm.provider_name_len = provider_name_len + 1;
1084 location_tracepoint_comm.binary_path_len = binary_path_len + 1;
1085
1086 if (buffer) {
1087 ret = lttng_dynamic_buffer_append(buffer,
1088 &location_tracepoint_comm,
1089 sizeof(location_tracepoint_comm));
1090 if (ret) {
1091 ret = -LTTNG_ERR_INVALID;
1092 goto end;
1093 }
1094 ret = lttng_dynamic_buffer_append(buffer,
1095 location_tracepoint->probe_name,
1096 location_tracepoint_comm.probe_name_len);
1097 if (ret) {
1098 ret = -LTTNG_ERR_INVALID;
1099 goto end;
1100 }
1101 ret = lttng_dynamic_buffer_append(buffer,
1102 location_tracepoint->provider_name,
1103 location_tracepoint_comm.provider_name_len);
1104 if (ret) {
1105 ret = -LTTNG_ERR_INVALID;
1106 goto end;
1107 }
1108 ret = lttng_dynamic_buffer_append(buffer,
1109 location_tracepoint->binary_path,
1110 location_tracepoint_comm.binary_path_len);
1111 if (ret) {
1112 ret = -LTTNG_ERR_INVALID;
1113 goto end;
1114 }
1115 }
1116 ret = sizeof(location_tracepoint_comm) +
1117 location_tracepoint_comm.probe_name_len +
1118 location_tracepoint_comm.provider_name_len +
1119 location_tracepoint_comm.binary_path_len;
1120 end:
1121 return ret;
1122 }
1123
1124 LTTNG_HIDDEN
1125 int lttng_userspace_probe_location_serialize(
1126 const struct lttng_userspace_probe_location *location,
1127 struct lttng_dynamic_buffer *buffer,
1128 int *binary_fd)
1129 {
1130 int ret, buffer_use = 0;
1131 struct lttng_userspace_probe_location_comm location_generic_comm;
1132
1133 if (!location) {
1134 ERR("Invalid argument(s)");
1135 ret = -LTTNG_ERR_INVALID;
1136 goto end;
1137 }
1138
1139 memset(&location_generic_comm, 0, sizeof(location_generic_comm));
1140
1141 location_generic_comm.type = (int8_t) location->type;
1142 if (buffer) {
1143 ret = lttng_dynamic_buffer_append(buffer, &location_generic_comm,
1144 sizeof(location_generic_comm));
1145 if (ret) {
1146 goto end;
1147 }
1148 }
1149 buffer_use += sizeof(location_generic_comm);
1150
1151 switch (lttng_userspace_probe_location_get_type(location)) {
1152 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1153 ret = lttng_userspace_probe_location_function_serialize(
1154 location, buffer, binary_fd);
1155 break;
1156 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1157 ret = lttng_userspace_probe_location_tracepoint_serialize(
1158 location, buffer, binary_fd);
1159 break;
1160 default:
1161 ERR("Unsupported probe location type");
1162 ret = -LTTNG_ERR_INVALID;
1163 goto end;
1164 }
1165 if (ret < 0) {
1166 goto end;
1167 }
1168 buffer_use += ret;
1169
1170 ret = lttng_userspace_probe_location_lookup_method_serialize(
1171 location->lookup_method, buffer);
1172 if (ret < 0) {
1173 goto end;
1174 }
1175 ret += buffer_use;
1176 end:
1177 return ret;
1178 }
1179
1180 static
1181 int lttng_userspace_probe_location_function_create_from_buffer(
1182 const struct lttng_buffer_view *buffer,
1183 struct lttng_userspace_probe_location **location)
1184 {
1185 struct lttng_userspace_probe_location_function_comm *location_function_comm;
1186 const char *function_name_src, *binary_path_src;
1187 char *function_name = NULL, *binary_path = NULL;
1188 int ret = 0;
1189
1190 assert(buffer);
1191 assert(buffer->data);
1192 assert(location);
1193
1194 location_function_comm =
1195 (struct lttng_userspace_probe_location_function_comm *) buffer->data;
1196
1197 const size_t expected_size = sizeof(*location_function_comm) +
1198 location_function_comm->function_name_len +
1199 location_function_comm->binary_path_len;
1200
1201 if (buffer->size < expected_size) {
1202 ret = -LTTNG_ERR_INVALID;
1203 goto end;
1204 }
1205
1206 function_name_src = buffer->data + sizeof(*location_function_comm);
1207 binary_path_src = function_name_src +
1208 location_function_comm->function_name_len;
1209
1210 if (function_name_src[location_function_comm->function_name_len - 1] != '\0') {
1211 ret = -LTTNG_ERR_INVALID;
1212 goto end;
1213 }
1214 if (binary_path_src[location_function_comm->binary_path_len - 1] != '\0') {
1215 ret = -LTTNG_ERR_INVALID;
1216 goto end;
1217 }
1218
1219 function_name = lttng_strndup(function_name_src, LTTNG_SYMBOL_NAME_LEN);
1220 if (!function_name) {
1221 PERROR("lttng_strndup");
1222 goto end;
1223 }
1224
1225 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1226 if (!binary_path) {
1227 PERROR("lttng_strndup");
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 /* Should we use the getter here? */
1855 if (a->type != b->type) {
1856 goto end;
1857 }
1858
1859 /* Not much else to compare except the type for now */
1860 is_equal = true;
1861 end:
1862 return is_equal;
1863 }
1864
1865 LTTNG_HIDDEN
1866 bool lttng_userspace_probe_location_is_equal(
1867 const struct lttng_userspace_probe_location *a,
1868 const struct lttng_userspace_probe_location *b)
1869 {
1870 bool is_equal = false;
1871
1872 if (!a || !b) {
1873 goto end;
1874 }
1875
1876 if (a == b) {
1877 is_equal = true;
1878 goto end;
1879 }
1880
1881 /* Should we use the getter here? */
1882 if (!lttng_userspace_probe_location_lookup_method_is_equal(
1883 a->lookup_method, b->lookup_method)) {
1884 goto end;
1885 }
1886
1887 /* Should we use the getter here? */
1888 if (a->type != b->type) {
1889 goto end;
1890 }
1891
1892 is_equal = a->equal ? a->equal(a, b) : true;
1893 end:
1894 return is_equal;
1895 }
1896
1897 LTTNG_HIDDEN
1898 int lttng_userspace_probe_location_set_binary_fd(
1899 struct lttng_userspace_probe_location *location, int fd)
1900 {
1901 int ret = 0;
1902 const struct lttng_userspace_probe_location_lookup_method *lookup = NULL;
1903 /*
1904 * Set the file descriptor received from the client through the unix
1905 * socket in the probe location.
1906 */
1907 lookup = lttng_userspace_probe_location_get_lookup_method(location);
1908 if (!lookup) {
1909 ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
1910 goto end;
1911 }
1912
1913 /*
1914 * From the kernel tracer's perspective, all userspace probe event types
1915 * are all the same: a file and an offset.
1916 */
1917 switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) {
1918 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
1919 ret = lttng_userspace_probe_location_function_set_binary_fd(
1920 location, fd);
1921 break;
1922 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
1923 ret = lttng_userspace_probe_location_tracepoint_set_binary_fd(
1924 location, fd);
1925 break;
1926 default:
1927 ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
1928 goto end;
1929 }
1930
1931 if (ret) {
1932 ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
1933 goto end;
1934 }
1935 end:
1936 return ret;
1937 }
This page took 0.128101 seconds and 5 git commands to generate.