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