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