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