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