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