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