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