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