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