5bbaccc572d5a296ab1d4fdd5d2d607e5abd7d95
[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 ret = -LTTNG_ERR_NOMEM;
1100 goto end;
1101 }
1102
1103 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1104 if (!binary_path) {
1105 PERROR("lttng_strndup");
1106 ret = -LTTNG_ERR_NOMEM;
1107 goto end;
1108 }
1109
1110 *location = lttng_userspace_probe_location_function_create_no_check(
1111 binary_path, function_name, NULL, false);
1112 if (!(*location)) {
1113 ret = -LTTNG_ERR_INVALID;
1114 goto end;
1115 }
1116
1117 ret = (int) expected_size;
1118 end:
1119 free(function_name);
1120 free(binary_path);
1121 return ret;
1122 }
1123
1124 static
1125 int lttng_userspace_probe_location_tracepoint_create_from_buffer(
1126 const struct lttng_buffer_view *buffer,
1127 struct lttng_userspace_probe_location **location)
1128 {
1129 struct lttng_userspace_probe_location_tracepoint_comm *location_tracepoint_comm;
1130 const char *probe_name_src, *provider_name_src, *binary_path_src;
1131 char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
1132 int ret = 0;
1133
1134 assert(buffer);
1135 assert(buffer->data);
1136 assert(location);
1137
1138 location_tracepoint_comm =
1139 (struct lttng_userspace_probe_location_tracepoint_comm *) buffer->data;
1140
1141 const size_t expected_size = sizeof(*location_tracepoint_comm) +
1142 location_tracepoint_comm->probe_name_len +
1143 location_tracepoint_comm->provider_name_len +
1144 location_tracepoint_comm->binary_path_len;
1145
1146 if (buffer->size < expected_size) {
1147 ret = -LTTNG_ERR_INVALID;
1148 goto end;
1149 }
1150
1151 probe_name_src = buffer->data + sizeof(*location_tracepoint_comm);
1152 provider_name_src = probe_name_src +
1153 location_tracepoint_comm->probe_name_len;
1154 binary_path_src = provider_name_src +
1155 location_tracepoint_comm->provider_name_len;
1156
1157 if (probe_name_src[location_tracepoint_comm->probe_name_len - 1] != '\0') {
1158 ret = -LTTNG_ERR_INVALID;
1159 goto end;
1160 }
1161
1162 if (provider_name_src[location_tracepoint_comm->provider_name_len - 1] != '\0') {
1163 ret = -LTTNG_ERR_INVALID;
1164 goto end;
1165 }
1166
1167 if (binary_path_src[location_tracepoint_comm->binary_path_len - 1] != '\0') {
1168 ret = -LTTNG_ERR_INVALID;
1169 goto end;
1170 }
1171
1172 probe_name = lttng_strndup(probe_name_src, LTTNG_SYMBOL_NAME_LEN);
1173 if (!probe_name) {
1174 PERROR("lttng_strndup");
1175 goto end;
1176 }
1177 provider_name = lttng_strndup(provider_name_src, LTTNG_SYMBOL_NAME_LEN);
1178 if (!provider_name) {
1179 PERROR("lttng_strndup");
1180 goto end;
1181 }
1182
1183 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1184 if (!binary_path) {
1185 PERROR("lttng_strndup");
1186 goto end;
1187 }
1188
1189 *location = lttng_userspace_probe_location_tracepoint_create_no_check(
1190 binary_path, provider_name, probe_name, NULL, false);
1191 if (!(*location)) {
1192 ret = -LTTNG_ERR_INVALID;
1193 goto end;
1194 }
1195
1196 ret = (int) expected_size;
1197 end:
1198 free(probe_name);
1199 free(provider_name);
1200 free(binary_path);
1201 return ret;
1202 }
1203
1204 static
1205 int lttng_userspace_probe_location_lookup_method_create_from_buffer(
1206 struct lttng_buffer_view *buffer,
1207 struct lttng_userspace_probe_location_lookup_method **lookup_method)
1208 {
1209 int ret;
1210 struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
1211 enum lttng_userspace_probe_location_lookup_method_type type;
1212
1213 assert(buffer);
1214 assert(buffer->data);
1215 assert(lookup_method);
1216
1217 if (buffer->size < sizeof(*lookup_comm)) {
1218 ret = -LTTNG_ERR_INVALID;
1219 goto end;
1220 }
1221
1222 lookup_comm = (struct lttng_userspace_probe_location_lookup_method_comm *)
1223 buffer->data;
1224 type = (enum lttng_userspace_probe_location_lookup_method_type)
1225 lookup_comm->type;
1226 switch (type) {
1227 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
1228 *lookup_method = NULL;
1229 break;
1230 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
1231 *lookup_method =
1232 lttng_userspace_probe_location_lookup_method_function_elf_create();
1233 if (!(*lookup_method)) {
1234 ret = -LTTNG_ERR_INVALID;
1235 goto end;
1236 }
1237 break;
1238 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
1239 *lookup_method =
1240 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1241 if (!(*lookup_method)) {
1242 ret = -LTTNG_ERR_INVALID;
1243 goto end;
1244 }
1245 break;
1246 default:
1247 ret = -LTTNG_ERR_INVALID;
1248 goto end;
1249 }
1250
1251 ret = sizeof(*lookup_comm);
1252 end:
1253 return ret;
1254 }
1255
1256 LTTNG_HIDDEN
1257 int lttng_userspace_probe_location_create_from_buffer(
1258 const struct lttng_buffer_view *buffer,
1259 struct lttng_userspace_probe_location **location)
1260 {
1261 struct lttng_userspace_probe_location_lookup_method *lookup_method;
1262 struct lttng_userspace_probe_location_comm *probe_location_comm;
1263 enum lttng_userspace_probe_location_type type;
1264 struct lttng_buffer_view lookup_method_view;
1265 int consumed = 0;
1266 int ret;
1267
1268
1269 assert(buffer);
1270 assert(buffer->data);
1271 assert(location);
1272
1273 lookup_method = NULL;
1274
1275 if (buffer->size <= sizeof(*probe_location_comm)) {
1276 ret = -LTTNG_ERR_INVALID;
1277 goto end;
1278 }
1279
1280 probe_location_comm =
1281 (struct lttng_userspace_probe_location_comm *) buffer->data;
1282 type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
1283 consumed += sizeof(*probe_location_comm);
1284
1285 switch (type) {
1286 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1287 {
1288 struct lttng_buffer_view view = lttng_buffer_view_from_view(
1289 buffer, consumed, buffer->size - consumed);
1290
1291 ret = lttng_userspace_probe_location_function_create_from_buffer(
1292 &view, location);
1293 if (ret < 0) {
1294 goto end;
1295 }
1296 break;
1297 }
1298 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1299 {
1300 struct lttng_buffer_view view = lttng_buffer_view_from_view(
1301 buffer, consumed, buffer->size - consumed);
1302
1303 ret = lttng_userspace_probe_location_tracepoint_create_from_buffer(
1304 &view, location);
1305 if (ret < 0) {
1306 goto end;
1307 }
1308 break;
1309 }
1310 default:
1311 ret = -LTTNG_ERR_INVALID;
1312 goto end;
1313 }
1314
1315 consumed += ret;
1316 if (buffer->size <= consumed) {
1317 ret = -LTTNG_ERR_INVALID;
1318 goto end;
1319 }
1320
1321 lookup_method_view = lttng_buffer_view_from_view(buffer, consumed,
1322 buffer->size - consumed);
1323 ret = lttng_userspace_probe_location_lookup_method_create_from_buffer(
1324 &lookup_method_view, &lookup_method);
1325 if (ret < 0) {
1326 ret = -LTTNG_ERR_INVALID;
1327 goto end;
1328 }
1329
1330 assert(lookup_method);
1331 (*location)->lookup_method = lookup_method;
1332 lookup_method = NULL;
1333 ret += consumed;
1334 end:
1335 return ret;
1336 }
1337
1338 LTTNG_HIDDEN
1339 int lttng_userspace_probe_location_function_set_binary_fd(
1340 struct lttng_userspace_probe_location *location, int binary_fd)
1341 {
1342 int ret = 0;
1343 struct lttng_userspace_probe_location_function *function_location;
1344
1345 assert(location);
1346 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1347
1348 function_location = container_of(location,
1349 struct lttng_userspace_probe_location_function, parent);
1350 if (function_location->binary_fd >= 0) {
1351 ret = close(function_location->binary_fd);
1352 if (ret) {
1353 PERROR("close");
1354 ret = -LTTNG_ERR_INVALID;
1355 goto end;
1356 }
1357 }
1358
1359 function_location->binary_fd = binary_fd;
1360 end:
1361 return ret;
1362 }
1363
1364 LTTNG_HIDDEN
1365 int lttng_userspace_probe_location_tracepoint_set_binary_fd(
1366 struct lttng_userspace_probe_location *location, int binary_fd)
1367 {
1368 int ret = 0;
1369 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
1370
1371 assert(location);
1372 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1373
1374 tracepoint_location = container_of(location,
1375 struct lttng_userspace_probe_location_tracepoint, parent);
1376 if (tracepoint_location->binary_fd >= 0) {
1377 ret = close(tracepoint_location->binary_fd);
1378 if (ret) {
1379 PERROR("close");
1380 ret = -LTTNG_ERR_INVALID;
1381 goto end;
1382 }
1383 }
1384
1385 tracepoint_location->binary_fd = binary_fd;
1386 end:
1387 return ret;
1388 }
1389
1390 static
1391 int lttng_userspace_probe_location_function_flatten(
1392 const struct lttng_userspace_probe_location *location,
1393 struct lttng_dynamic_buffer *buffer)
1394 {
1395 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method;
1396 struct lttng_userspace_probe_location_function *probe_function;
1397 struct lttng_userspace_probe_location_function flat_probe;
1398 size_t function_name_len, binary_path_len;
1399 size_t padding_needed = 0;
1400 char *flat_probe_start;
1401 int storage_needed = 0;
1402 int ret;
1403
1404 assert(location);
1405
1406 if (location->lookup_method && location->lookup_method->type !=
1407 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF) {
1408 ret = -LTTNG_ERR_INVALID;
1409 goto end;
1410 }
1411
1412 probe_function = container_of(location,
1413 struct lttng_userspace_probe_location_function,
1414 parent);
1415 assert(probe_function->function_name);
1416 assert(probe_function->binary_path);
1417
1418 storage_needed +=
1419 sizeof(struct lttng_userspace_probe_location_function);
1420 function_name_len = strlen(probe_function->function_name) + 1;
1421 binary_path_len = strlen(probe_function->binary_path) + 1;
1422 storage_needed += function_name_len + binary_path_len;
1423
1424 /*
1425 * The lookup method is aligned to 64-bit within the buffer.
1426 * This is needed even if there is no lookup method since
1427 * the next structure in the buffer probably needs to be
1428 * aligned too (depending on the arch).
1429 */
1430 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1431 storage_needed += padding_needed;
1432
1433 if (location->lookup_method) {
1434 /* NOTE: elf look-up method is assumed here. */
1435 storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1436 }
1437
1438 if (!buffer) {
1439 ret = storage_needed;
1440 goto end;
1441 }
1442
1443 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1444 ret = lttng_dynamic_buffer_set_capacity(buffer,
1445 buffer->size + storage_needed);
1446 if (ret) {
1447 goto end;
1448 }
1449 }
1450
1451 memset(&flat_probe, 0, sizeof(flat_probe));
1452
1453 flat_probe_start = buffer->data + buffer->size;
1454 flat_probe.parent.type = location->type;
1455 /*
1456 * The lookup method, if present, is the last element in the flat
1457 * representation of the probe.
1458 */
1459 if (location->lookup_method) {
1460 flat_probe.parent.lookup_method =
1461 (struct lttng_userspace_probe_location_lookup_method *)
1462 (flat_probe_start + sizeof(flat_probe) +
1463 function_name_len + binary_path_len + padding_needed);
1464 } else {
1465 flat_probe.parent.lookup_method = NULL;
1466 }
1467
1468 flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
1469 flat_probe.binary_path = flat_probe.function_name + function_name_len;
1470 flat_probe.binary_fd = -1;
1471 ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
1472 sizeof(flat_probe));
1473 if (ret) {
1474 goto end;
1475 }
1476
1477 ret = lttng_dynamic_buffer_append(buffer,
1478 probe_function->function_name, function_name_len);
1479 if (ret) {
1480 goto end;
1481 }
1482 ret = lttng_dynamic_buffer_append(buffer,
1483 probe_function->binary_path, binary_path_len);
1484 if (ret) {
1485 goto end;
1486 }
1487
1488 /* Insert padding before the lookup method. */
1489 ret = lttng_dynamic_buffer_set_size(buffer,
1490 buffer->size + padding_needed);
1491 if (ret) {
1492 goto end;
1493 }
1494
1495 if (!location->lookup_method) {
1496 /* Not an error, the default method is used. */
1497 ret = storage_needed;
1498 goto end;
1499 }
1500
1501 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1502 flat_lookup_method.parent.type =
1503 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
1504 ret = lttng_dynamic_buffer_append(buffer,
1505 &flat_lookup_method, sizeof(flat_lookup_method));
1506 if (ret) {
1507 goto end;
1508 }
1509 ret = storage_needed;
1510 end:
1511 return ret;
1512 }
1513
1514 static
1515 int lttng_userspace_probe_location_tracepoint_flatten(
1516 const struct lttng_userspace_probe_location *location,
1517 struct lttng_dynamic_buffer *buffer)
1518 {
1519 struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method;
1520 struct lttng_userspace_probe_location_tracepoint *probe_tracepoint;
1521 struct lttng_userspace_probe_location_tracepoint flat_probe;
1522 size_t probe_name_len, provider_name_len, binary_path_len;
1523 size_t padding_needed = 0;
1524 int storage_needed = 0;
1525 char *flat_probe_start;
1526 int ret = 0;
1527
1528 assert(location);
1529
1530 /* Only SDT tracepoints are supported at the moment */
1531 if (location->lookup_method && location->lookup_method->type !=
1532 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT) {
1533 ret = -LTTNG_ERR_INVALID;
1534 goto end;
1535 }
1536 probe_tracepoint = container_of(location,
1537 struct lttng_userspace_probe_location_tracepoint,
1538 parent);
1539 assert(probe_tracepoint->probe_name);
1540 assert(probe_tracepoint->provider_name);
1541 assert(probe_tracepoint->binary_path);
1542
1543 /* Compute the storage space needed to flatten the probe location */
1544 storage_needed += sizeof(struct lttng_userspace_probe_location_tracepoint);
1545
1546 probe_name_len = strlen(probe_tracepoint->probe_name) + 1;
1547 provider_name_len = strlen(probe_tracepoint->provider_name) + 1;
1548 binary_path_len = strlen(probe_tracepoint->binary_path) + 1;
1549
1550 storage_needed += probe_name_len + provider_name_len + binary_path_len;
1551
1552 /*
1553 * The lookup method is aligned to 64-bit within the buffer.
1554 * This is needed even if there is no lookup method since
1555 * the next structure in the buffer probably needs to be
1556 * aligned too (depending on the arch).
1557 */
1558 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1559 storage_needed += padding_needed;
1560
1561 if (location->lookup_method) {
1562 /* NOTE: elf look-up method is assumed here. */
1563 storage_needed +=
1564 sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1565 }
1566
1567 /*
1568 * If the caller set buffer to NULL, return the size of the needed buffer.
1569 */
1570 if (!buffer) {
1571 ret = storage_needed;
1572 goto end;
1573 }
1574
1575 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1576 ret = lttng_dynamic_buffer_set_capacity(buffer,
1577 buffer->size + storage_needed);
1578 if (ret) {
1579 goto end;
1580 }
1581 }
1582
1583 memset(&flat_probe, 0, sizeof(flat_probe));
1584
1585 flat_probe_start = buffer->data + buffer->size;
1586 flat_probe.parent.type = location->type;
1587
1588 /*
1589 * The lookup method, if present, is the last element in the flat
1590 * representation of the probe.
1591 */
1592 if (location->lookup_method) {
1593 flat_probe.parent.lookup_method =
1594 (struct lttng_userspace_probe_location_lookup_method *)
1595 (flat_probe_start + sizeof(flat_probe) +
1596 probe_name_len + provider_name_len +
1597 binary_path_len + padding_needed);
1598 } else {
1599 flat_probe.parent.lookup_method = NULL;
1600 }
1601
1602 flat_probe.probe_name = flat_probe_start + sizeof(flat_probe);
1603 flat_probe.provider_name = flat_probe.probe_name + probe_name_len;
1604 flat_probe.binary_path = flat_probe.provider_name + provider_name_len;
1605 flat_probe.binary_fd = -1;
1606 ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe));
1607 if (ret) {
1608 goto end;
1609 }
1610
1611 /* Append all the fields to the buffer */
1612 ret = lttng_dynamic_buffer_append(buffer,
1613 probe_tracepoint->probe_name, probe_name_len);
1614 if (ret) {
1615 goto end;
1616 }
1617 ret = lttng_dynamic_buffer_append(buffer,
1618 probe_tracepoint->provider_name, provider_name_len);
1619 if (ret) {
1620 goto end;
1621 }
1622 ret = lttng_dynamic_buffer_append(buffer,
1623 probe_tracepoint->binary_path, binary_path_len);
1624 if (ret) {
1625 goto end;
1626 }
1627
1628 /* Insert padding before the lookup method. */
1629 ret = lttng_dynamic_buffer_set_size(buffer, buffer->size + padding_needed);
1630 if (ret) {
1631 goto end;
1632 }
1633
1634 if (!location->lookup_method) {
1635 /* Not an error, the default method is used. */
1636 ret = storage_needed;
1637 goto end;
1638 }
1639
1640 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1641
1642 flat_lookup_method.parent.type =
1643 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
1644 ret = lttng_dynamic_buffer_append(buffer,
1645 &flat_lookup_method, sizeof(flat_lookup_method));
1646 if (ret) {
1647 goto end;
1648 }
1649 ret = storage_needed;
1650 end:
1651 return ret;
1652 }
1653
1654 LTTNG_HIDDEN
1655 int lttng_userspace_probe_location_flatten(
1656 const struct lttng_userspace_probe_location *location,
1657 struct lttng_dynamic_buffer *buffer)
1658 {
1659 int ret;
1660 if (!location) {
1661 ret = -LTTNG_ERR_INVALID;
1662 goto end;
1663 }
1664
1665 /* Only types currently supported. */
1666 switch (location->type) {
1667 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1668 ret = lttng_userspace_probe_location_function_flatten(location, buffer);
1669 break;
1670 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1671 ret = lttng_userspace_probe_location_tracepoint_flatten(location, buffer);
1672 break;
1673 default:
1674 ret = -LTTNG_ERR_INVALID;
1675 goto end;
1676 }
1677
1678 end:
1679 return ret;
1680 }
1681
1682 LTTNG_HIDDEN
1683 struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
1684 const struct lttng_userspace_probe_location *location)
1685 {
1686 struct lttng_userspace_probe_location *new_location = NULL;
1687 enum lttng_userspace_probe_location_type type;
1688
1689 if (!location) {
1690 goto err;
1691 }
1692
1693 type = lttng_userspace_probe_location_get_type(location);
1694 switch (type) {
1695 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1696 new_location =
1697 lttng_userspace_probe_location_function_copy(location);
1698 if (!new_location) {
1699 goto err;
1700 }
1701 break;
1702 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1703 new_location =
1704 lttng_userspace_probe_location_tracepoint_copy(location);
1705 if (!new_location) {
1706 goto err;
1707 }
1708 break;
1709 default:
1710 new_location = NULL;
1711 goto err;
1712 }
1713 err:
1714 return new_location;
1715 }
This page took 0.085872 seconds and 4 git commands to generate.