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