Move to kernel style SPDX license identifiers
[lttng-tools.git] / src / common / userspace-probe.c
CommitLineData
1ce46cfe 1/*
ab5be9fa 2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
1ce46cfe 3 *
ab5be9fa 4 * SPDX-License-Identifier: LGPL-2.1-only
1ce46cfe 5 *
1ce46cfe
JG
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
16enum lttng_userspace_probe_location_lookup_method_type
17lttng_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
24void 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
5d21f143 31 free(lookup_method);
1ce46cfe
JG
32}
33
34struct lttng_userspace_probe_location_lookup_method *
35lttng_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;
48end:
49 return ret;
50}
51
f4d0bb2e
FD
52struct lttng_userspace_probe_location_lookup_method *
53lttng_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;
66end:
67 return ret;
68}
69
1ce46cfe
JG
70enum 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
77static
78void 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
f4d0bb2e
FD
100static
101void 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
1ce46cfe
JG
125void 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;
f4d0bb2e
FD
139 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
140 lttng_userspace_probe_location_tracepoint_destroy(location);
141 break;
1ce46cfe 142 default:
adf53c67 143 abort();
1ce46cfe
JG
144 }
145}
146
147static struct lttng_userspace_probe_location *
148lttng_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;
9d3981b5
JG
189 location->instrumentation_type =
190 LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY;
1ce46cfe
JG
191
192 ret = &location->parent;
193 ret->lookup_method = lookup_method;
194 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION;
195 goto end;
196
197error:
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 }
205end:
206 return ret;
207}
208
f4d0bb2e
FD
209static struct lttng_userspace_probe_location *
210lttng_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
266error:
267 free(probe_name_copy);
268 free(provider_name_copy);
7c86453b 269 free(binary_path_copy);
f4d0bb2e
FD
270 if (binary_fd >= 0) {
271 if (close(binary_fd)) {
272 PERROR("Error closing binary fd in error path");
273 }
274 }
275end:
276 return ret;
277}
278
1ce46cfe
JG
279struct lttng_userspace_probe_location *
280lttng_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);
303end:
304 return ret;
305}
306
f4d0bb2e
FD
307struct lttng_userspace_probe_location *
308lttng_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);
330end:
331 return ret;
332}
333
394357fe
FD
334static struct lttng_userspace_probe_location_lookup_method *
335lttng_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;
355error:
356 parent = NULL;
357end:
358 return parent;
359}
360
f4d0bb2e
FD
361static struct lttng_userspace_probe_location_lookup_method *
362lttng_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
383error:
384 parent = NULL;
385end:
386 return parent;
387}
388
394357fe
FD
389static struct lttng_userspace_probe_location *
390lttng_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;
cc831309
FD
396 const char *binary_path = NULL;
397 const char *function_name = NULL;
d7ee7196 398 int fd, new_fd;
394357fe
FD
399
400 assert(location);
401 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
402
cc831309
FD
403 /* Get probe location fields */
404 binary_path = lttng_userspace_probe_location_function_get_binary_path(location);
394357fe 405 if (!binary_path) {
cc831309 406 ERR("Userspace probe binary path is NULL");
394357fe
FD
407 goto error;
408 }
409
cc831309 410 function_name = lttng_userspace_probe_location_function_get_function_name(location);
394357fe 411 if (!function_name) {
cc831309 412 ERR("Userspace probe function name is NULL");
394357fe
FD
413 goto error;
414 }
415
416 /* Duplicate the binary fd */
d7ee7196 417 fd = lttng_userspace_probe_location_function_get_binary_fd(location);
394357fe 418 if (fd == -1) {
d7ee7196
FD
419 ERR("Error getting file descriptor to binary");
420 goto error;
421 }
422
423 new_fd = dup(fd);
424 if (new_fd == -1) {
394357fe
FD
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(
cc831309 450 binary_path, function_name, lookup_method, false);
394357fe
FD
451 if (!new_location) {
452 goto destroy_lookup_method;
453 }
454
455 /* Set the duplicated fd to the new probe_location */
d7ee7196 456 if (lttng_userspace_probe_location_function_set_binary_fd(new_location, new_fd) < 0) {
394357fe
FD
457 goto destroy_probe_location;
458 }
459
460 goto end;
461
462destroy_probe_location:
463 lttng_userspace_probe_location_destroy(new_location);
464destroy_lookup_method:
465 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
466close_fd:
d7ee7196 467 if (close(new_fd) < 0) {
394357fe
FD
468 PERROR("Error closing duplicated file descriptor in error path");
469 }
470error:
394357fe
FD
471 new_location = NULL;
472end:
473 return new_location;
474}
475
f4d0bb2e
FD
476static struct lttng_userspace_probe_location *
477lttng_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;
cc831309
FD
483 const char *binary_path = NULL;
484 const char *probe_name = NULL;
485 const char *provider_name = NULL;
d7ee7196 486 int fd, new_fd;
f4d0bb2e
FD
487
488 assert(location);
489 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
490
cc831309
FD
491 /* Get probe location fields */
492 binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(location);
f4d0bb2e 493 if (!binary_path) {
cc831309 494 ERR("Userspace probe binary path is NULL");
f4d0bb2e
FD
495 goto error;
496 }
497
cc831309 498 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(location);
f4d0bb2e 499 if (!probe_name) {
cc831309 500 ERR("Userspace probe probe name is NULL");
f4d0bb2e
FD
501 goto error;
502 }
503
cc831309 504 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(location);
f4d0bb2e 505 if (!provider_name) {
cc831309 506 ERR("Userspace probe provider name is NULL");
f4d0bb2e
FD
507 goto error;
508 }
509
510 /* Duplicate the binary fd */
d7ee7196 511 fd = lttng_userspace_probe_location_tracepoint_get_binary_fd(location);
f4d0bb2e 512 if (fd == -1) {
d7ee7196
FD
513 ERR("Error getting file descriptor to binary");
514 goto error;
515 }
516
517 new_fd = dup(fd);
518 if (new_fd == -1) {
cc831309 519 PERROR("Error duplicating file descriptor to binary");
f4d0bb2e
FD
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(
cc831309 544 binary_path, provider_name, probe_name, lookup_method, false);
f4d0bb2e
FD
545 if (!new_location) {
546 goto destroy_lookup_method;
547 }
548
549 /* Set the duplicated fd to the new probe_location */
d7ee7196 550 if (lttng_userspace_probe_location_tracepoint_set_binary_fd(new_location, new_fd) < 0) {
f4d0bb2e
FD
551 goto destroy_probe_location;
552 }
553
554 goto end;
555
556destroy_probe_location:
557 lttng_userspace_probe_location_destroy(new_location);
558destroy_lookup_method:
559 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
560close_fd:
d7ee7196 561 if (close(new_fd) < 0) {
cc831309 562 PERROR("Error closing duplicated file descriptor in error path");
f4d0bb2e
FD
563 }
564error:
f4d0bb2e
FD
565 new_location = NULL;
566end:
567 return new_location;
568}
569
1ce46cfe
JG
570const 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;
586end:
587 return ret;
588}
589
f4d0bb2e
FD
590const 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;
606end:
607 return ret;
608}
609
1ce46cfe
JG
610const 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;
625end:
626 return ret;
627}
628
f4d0bb2e
FD
629const 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;
644end:
645 return ret;
646}
647
648const 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;
663end:
664 return ret;
665}
666
1ce46cfe
JG
667int 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;
682end:
683 return ret;
684}
685
9d3981b5
JG
686enum lttng_userspace_probe_location_function_instrumentation_type
687lttng_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;
703end:
704 return type;
705}
706
707enum lttng_userspace_probe_location_status
708lttng_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;
728end:
729 return status;
730}
731
f4d0bb2e
FD
732int 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;
747end:
748 return ret;
749}
750
1ce46cfe
JG
751static struct lttng_userspace_probe_location_lookup_method *
752lttng_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;
764end:
765 return ret;
766}
767
f4d0bb2e
FD
768static struct lttng_userspace_probe_location_lookup_method *
769lttng_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;
781end:
782 return ret;
783}
784
87597c2c 785const struct lttng_userspace_probe_location_lookup_method *
1ce46cfe
JG
786lttng_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;
f4d0bb2e
FD
797 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
798 ret = lttng_userspace_probe_location_tracepoint_get_lookup_method(
799 location);
800 break;
1ce46cfe
JG
801 default:
802 ERR("Unknowned lookup method.");
803 break;
804 }
805 return ret;
806}
807
808static
809int 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 }
f4d0bb2e
FD
826 ret = sizeof(lookup_method_comm);
827end:
828 return ret;
829}
830
831static
832int 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;
1ce46cfe
JG
903end:
904 return ret;
905}
906
907static
f4d0bb2e 908int lttng_userspace_probe_location_tracepoint_serialize(
1ce46cfe
JG
909 const struct lttng_userspace_probe_location *location,
910 struct lttng_dynamic_buffer *buffer,
911 int *binary_fd)
912{
913 int ret;
f4d0bb2e
FD
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;
1ce46cfe
JG
917
918 assert(location);
919 assert(lttng_userspace_probe_location_get_type(location) ==
f4d0bb2e 920 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1ce46cfe 921
f4d0bb2e
FD
922 location_tracepoint = container_of(location,
923 struct lttng_userspace_probe_location_tracepoint,
1ce46cfe 924 parent);
f4d0bb2e
FD
925 if (!location_tracepoint->probe_name ||
926 !location_tracepoint->provider_name ||
927 !location_tracepoint->binary_path) {
1ce46cfe
JG
928 ret = -LTTNG_ERR_INVALID;
929 goto end;
930 }
931
f4d0bb2e 932 if (binary_fd && location_tracepoint->binary_fd < 0) {
1ce46cfe
JG
933 ret = -LTTNG_ERR_INVALID;
934 goto end;
935 }
936
937 if (binary_fd) {
f4d0bb2e 938 *binary_fd = location_tracepoint->binary_fd;
1ce46cfe
JG
939 }
940
f4d0bb2e
FD
941 probe_name_len = strlen(location_tracepoint->probe_name);
942 if (probe_name_len == 0) {
1ce46cfe
JG
943 ret = -LTTNG_ERR_INVALID;
944 goto end;
945 }
f4d0bb2e
FD
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);
1ce46cfe
JG
954 if (binary_path_len == 0) {
955 ret = -LTTNG_ERR_INVALID;
956 goto end;
957 }
958
f4d0bb2e
FD
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;
1ce46cfe
JG
962
963 if (buffer) {
964 ret = lttng_dynamic_buffer_append(buffer,
f4d0bb2e
FD
965 &location_tracepoint_comm,
966 sizeof(location_tracepoint_comm));
1ce46cfe
JG
967 if (ret) {
968 ret = -LTTNG_ERR_INVALID;
969 goto end;
970 }
971 ret = lttng_dynamic_buffer_append(buffer,
f4d0bb2e
FD
972 location_tracepoint->probe_name,
973 location_tracepoint_comm.probe_name_len);
1ce46cfe
JG
974 if (ret) {
975 ret = -LTTNG_ERR_INVALID;
976 goto end;
977 }
978 ret = lttng_dynamic_buffer_append(buffer,
f4d0bb2e
FD
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);
1ce46cfe
JG
988 if (ret) {
989 ret = -LTTNG_ERR_INVALID;
990 goto end;
991 }
992 }
f4d0bb2e
FD
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;
1ce46cfe
JG
997end:
998 return ret;
999}
1000
1001LTTNG_HIDDEN
1002int 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
56f0bc67
JG
1016 memset(&location_generic_comm, 0, sizeof(location_generic_comm));
1017
1ce46cfe
JG
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;
f4d0bb2e
FD
1033 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1034 ret = lttng_userspace_probe_location_tracepoint_serialize(
1035 location, buffer, binary_fd);
1036 break;
1ce46cfe
JG
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;
1053end:
1054 return ret;
1055}
1056
1057static
1058int lttng_userspace_probe_location_function_create_from_buffer(
1059 const struct lttng_buffer_view *buffer,
1060 struct lttng_userspace_probe_location **location)
1061{
1062 struct lttng_userspace_probe_location_function_comm *location_function_comm;
1063 const char *function_name_src, *binary_path_src;
1064 char *function_name = NULL, *binary_path = NULL;
1065 int ret = 0;
1066
1067 assert(buffer);
1068 assert(buffer->data);
1069 assert(location);
1070
1071 location_function_comm =
1072 (struct lttng_userspace_probe_location_function_comm *) buffer->data;
1073
1074 const size_t expected_size = sizeof(*location_function_comm) +
1075 location_function_comm->function_name_len +
1076 location_function_comm->binary_path_len;
1077
1078 if (buffer->size < expected_size) {
1079 ret = -LTTNG_ERR_INVALID;
1080 goto end;
1081 }
1082
1083 function_name_src = buffer->data + sizeof(*location_function_comm);
1084 binary_path_src = function_name_src +
1085 location_function_comm->function_name_len;
1086
1087 if (function_name_src[location_function_comm->function_name_len - 1] != '\0') {
1088 ret = -LTTNG_ERR_INVALID;
1089 goto end;
1090 }
1091 if (binary_path_src[location_function_comm->binary_path_len - 1] != '\0') {
1092 ret = -LTTNG_ERR_INVALID;
1093 goto end;
1094 }
1095
1096 function_name = lttng_strndup(function_name_src, LTTNG_SYMBOL_NAME_LEN);
1097 if (!function_name) {
1098 PERROR("lttng_strndup");
1099 goto end;
1100 }
1101
1102 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1103 if (!binary_path) {
1104 PERROR("lttng_strndup");
1105 goto end;
1106 }
1107
1108 *location = lttng_userspace_probe_location_function_create_no_check(
1109 binary_path, function_name, NULL, false);
1110 if (!(*location)) {
1111 ret = -LTTNG_ERR_INVALID;
1112 goto end;
1113 }
1114
1115 ret = (int) expected_size;
1116end:
1117 free(function_name);
1118 free(binary_path);
1119 return ret;
1120}
1121
f4d0bb2e
FD
1122static
1123int lttng_userspace_probe_location_tracepoint_create_from_buffer(
1124 const struct lttng_buffer_view *buffer,
1125 struct lttng_userspace_probe_location **location)
1126{
1127 struct lttng_userspace_probe_location_tracepoint_comm *location_tracepoint_comm;
1128 const char *probe_name_src, *provider_name_src, *binary_path_src;
1129 char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
1130 int ret = 0;
1131
1132 assert(buffer);
1133 assert(buffer->data);
1134 assert(location);
1135
1136 location_tracepoint_comm =
1137 (struct lttng_userspace_probe_location_tracepoint_comm *) buffer->data;
1138
1139 const size_t expected_size = sizeof(*location_tracepoint_comm) +
1140 location_tracepoint_comm->probe_name_len +
1141 location_tracepoint_comm->provider_name_len +
1142 location_tracepoint_comm->binary_path_len;
1143
1144 if (buffer->size < expected_size) {
1145 ret = -LTTNG_ERR_INVALID;
1146 goto end;
1147 }
1148
1149 probe_name_src = buffer->data + sizeof(*location_tracepoint_comm);
1150 provider_name_src = probe_name_src +
1151 location_tracepoint_comm->probe_name_len;
1152 binary_path_src = provider_name_src +
1153 location_tracepoint_comm->provider_name_len;
1154
1155 if (probe_name_src[location_tracepoint_comm->probe_name_len - 1] != '\0') {
1156 ret = -LTTNG_ERR_INVALID;
1157 goto end;
1158 }
1159
1160 if (provider_name_src[location_tracepoint_comm->provider_name_len - 1] != '\0') {
1161 ret = -LTTNG_ERR_INVALID;
1162 goto end;
1163 }
1164
1165 if (binary_path_src[location_tracepoint_comm->binary_path_len - 1] != '\0') {
1166 ret = -LTTNG_ERR_INVALID;
1167 goto end;
1168 }
1169
1170 probe_name = lttng_strndup(probe_name_src, LTTNG_SYMBOL_NAME_LEN);
1171 if (!probe_name) {
1172 PERROR("lttng_strndup");
1173 goto end;
1174 }
1175 provider_name = lttng_strndup(provider_name_src, LTTNG_SYMBOL_NAME_LEN);
1176 if (!provider_name) {
1177 PERROR("lttng_strndup");
1178 goto end;
1179 }
1180
1181 binary_path = lttng_strndup(binary_path_src, LTTNG_SYMBOL_NAME_LEN);
1182 if (!binary_path) {
1183 PERROR("lttng_strndup");
1184 goto end;
1185 }
1186
1187 *location = lttng_userspace_probe_location_tracepoint_create_no_check(
1188 binary_path, provider_name, probe_name, NULL, false);
1189 if (!(*location)) {
1190 ret = -LTTNG_ERR_INVALID;
1191 goto end;
1192 }
1193
1194 ret = (int) expected_size;
1195end:
1196 free(probe_name);
1197 free(provider_name);
1198 free(binary_path);
1199 return ret;
1200}
1201
1ce46cfe
JG
1202static
1203int lttng_userspace_probe_location_lookup_method_create_from_buffer(
1204 struct lttng_buffer_view *buffer,
1205 struct lttng_userspace_probe_location_lookup_method **lookup_method)
1206{
1207 int ret;
1208 struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
1209 enum lttng_userspace_probe_location_lookup_method_type type;
1210
1211 assert(buffer);
1212 assert(buffer->data);
1213 assert(lookup_method);
1214
1215 if (buffer->size < sizeof(*lookup_comm)) {
1216 ret = -LTTNG_ERR_INVALID;
1217 goto end;
1218 }
1219
1220 lookup_comm = (struct lttng_userspace_probe_location_lookup_method_comm *)
1221 buffer->data;
1222 type = (enum lttng_userspace_probe_location_lookup_method_type)
1223 lookup_comm->type;
1224 switch (type) {
1225 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
1226 *lookup_method = NULL;
1227 break;
1228 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
1229 *lookup_method =
1230 lttng_userspace_probe_location_lookup_method_function_elf_create();
1231 if (!(*lookup_method)) {
1232 ret = -LTTNG_ERR_INVALID;
1233 goto end;
1234 }
1235 break;
f4d0bb2e
FD
1236 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
1237 *lookup_method =
1238 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1239 if (!(*lookup_method)) {
1240 ret = -LTTNG_ERR_INVALID;
1241 goto end;
1242 }
1243 break;
1ce46cfe
JG
1244 default:
1245 ret = -LTTNG_ERR_INVALID;
1246 goto end;
1247 }
1248
1249 ret = sizeof(*lookup_comm);
1250end:
1251 return ret;
1252}
1253
1254LTTNG_HIDDEN
1255int lttng_userspace_probe_location_create_from_buffer(
1256 const struct lttng_buffer_view *buffer,
1257 struct lttng_userspace_probe_location **location)
1258{
1259 struct lttng_userspace_probe_location_lookup_method *lookup_method;
1260 struct lttng_userspace_probe_location_comm *probe_location_comm;
1261 enum lttng_userspace_probe_location_type type;
1262 struct lttng_buffer_view lookup_method_view;
1263 int consumed = 0;
1264 int ret;
1265
1266
1267 assert(buffer);
1268 assert(buffer->data);
1269 assert(location);
1270
1271 lookup_method = NULL;
1272
1273 if (buffer->size <= sizeof(*probe_location_comm)) {
1274 ret = -LTTNG_ERR_INVALID;
1275 goto end;
1276 }
1277
1278 probe_location_comm =
1279 (struct lttng_userspace_probe_location_comm *) buffer->data;
1280 type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
1281 consumed += sizeof(*probe_location_comm);
1282
1283 switch (type) {
1284 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1285 {
1286 struct lttng_buffer_view view = lttng_buffer_view_from_view(
1287 buffer, consumed, buffer->size - consumed);
1288
1289 ret = lttng_userspace_probe_location_function_create_from_buffer(
1290 &view, location);
1291 if (ret < 0) {
1292 goto end;
1293 }
1294 break;
1295 }
f4d0bb2e
FD
1296 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1297 {
1298 struct lttng_buffer_view view = lttng_buffer_view_from_view(
1299 buffer, consumed, buffer->size - consumed);
1300
1301 ret = lttng_userspace_probe_location_tracepoint_create_from_buffer(
1302 &view, location);
1303 if (ret < 0) {
1304 goto end;
1305 }
1306 break;
1307 }
1ce46cfe
JG
1308 default:
1309 ret = -LTTNG_ERR_INVALID;
1310 goto end;
1311 }
1312
1313 consumed += ret;
1314 if (buffer->size <= consumed) {
1315 ret = -LTTNG_ERR_INVALID;
1316 goto end;
1317 }
1318
1319 lookup_method_view = lttng_buffer_view_from_view(buffer, consumed,
1320 buffer->size - consumed);
1321 ret = lttng_userspace_probe_location_lookup_method_create_from_buffer(
1322 &lookup_method_view, &lookup_method);
1323 if (ret < 0) {
1324 ret = -LTTNG_ERR_INVALID;
1325 goto end;
1326 }
1327
1328 assert(lookup_method);
1329 (*location)->lookup_method = lookup_method;
1330 lookup_method = NULL;
1331 ret += consumed;
1332end:
1333 return ret;
1334}
1335
1336LTTNG_HIDDEN
1337int lttng_userspace_probe_location_function_set_binary_fd(
1338 struct lttng_userspace_probe_location *location, int binary_fd)
1339{
1340 int ret = 0;
1341 struct lttng_userspace_probe_location_function *function_location;
1342
1343 assert(location);
1344 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1345
1346 function_location = container_of(location,
1347 struct lttng_userspace_probe_location_function, parent);
1348 if (function_location->binary_fd >= 0) {
1349 ret = close(function_location->binary_fd);
1350 if (ret) {
1351 PERROR("close");
1352 ret = -LTTNG_ERR_INVALID;
1353 goto end;
1354 }
1355 }
1356
1357 function_location->binary_fd = binary_fd;
1358end:
1359 return ret;
1360}
1361
f4d0bb2e
FD
1362LTTNG_HIDDEN
1363int lttng_userspace_probe_location_tracepoint_set_binary_fd(
1364 struct lttng_userspace_probe_location *location, int binary_fd)
1365{
1366 int ret = 0;
1367 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
1368
1369 assert(location);
1370 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1371
1372 tracepoint_location = container_of(location,
1373 struct lttng_userspace_probe_location_tracepoint, parent);
1374 if (tracepoint_location->binary_fd >= 0) {
1375 ret = close(tracepoint_location->binary_fd);
1376 if (ret) {
1377 PERROR("close");
1378 ret = -LTTNG_ERR_INVALID;
1379 goto end;
1380 }
1381 }
1382
1383 tracepoint_location->binary_fd = binary_fd;
1384end:
1385 return ret;
1386}
1387
1ce46cfe
JG
1388static
1389int lttng_userspace_probe_location_function_flatten(
1390 const struct lttng_userspace_probe_location *location,
1391 struct lttng_dynamic_buffer *buffer)
1392{
1393 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method;
1394 struct lttng_userspace_probe_location_function *probe_function;
1395 struct lttng_userspace_probe_location_function flat_probe;
1396 size_t function_name_len, binary_path_len;
1397 size_t padding_needed = 0;
1398 char *flat_probe_start;
1399 int storage_needed = 0;
1400 int ret;
1401
1402 assert(location);
1403
1404 if (location->lookup_method && location->lookup_method->type !=
1405 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF) {
1406 ret = -LTTNG_ERR_INVALID;
1407 goto end;
1408 }
1409
1410 probe_function = container_of(location,
1411 struct lttng_userspace_probe_location_function,
1412 parent);
1413 assert(probe_function->function_name);
1414 assert(probe_function->binary_path);
1415
1416 storage_needed +=
1417 sizeof(struct lttng_userspace_probe_location_function);
1418 function_name_len = strlen(probe_function->function_name) + 1;
1419 binary_path_len = strlen(probe_function->binary_path) + 1;
1420 storage_needed += function_name_len + binary_path_len;
1421
1422 /*
1423 * The lookup method is aligned to 64-bit within the buffer.
1424 * This is needed even if there is no lookup method since
1425 * the next structure in the buffer probably needs to be
1426 * aligned too (depending on the arch).
1427 */
1428 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1429 storage_needed += padding_needed;
1430
1431 if (location->lookup_method) {
1432 /* NOTE: elf look-up method is assumed here. */
1433 storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1434 }
1435
1436 if (!buffer) {
1437 ret = storage_needed;
1438 goto end;
1439 }
1440
1441 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1442 ret = lttng_dynamic_buffer_set_capacity(buffer,
1443 buffer->size + storage_needed);
1444 if (ret) {
1445 goto end;
1446 }
1447 }
1448
1449 memset(&flat_probe, 0, sizeof(flat_probe));
1450
1451 flat_probe_start = buffer->data + buffer->size;
1452 flat_probe.parent.type = location->type;
1453 /*
1454 * The lookup method, if present, is the last element in the flat
1455 * representation of the probe.
1456 */
1457 if (location->lookup_method) {
1458 flat_probe.parent.lookup_method =
1459 (struct lttng_userspace_probe_location_lookup_method *)
1460 (flat_probe_start + sizeof(flat_probe) +
1461 function_name_len + binary_path_len + padding_needed);
1462 } else {
1463 flat_probe.parent.lookup_method = NULL;
1464 }
1465
1466 flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
1467 flat_probe.binary_path = flat_probe.function_name + function_name_len;
1468 flat_probe.binary_fd = -1;
1469 ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
1470 sizeof(flat_probe));
1471 if (ret) {
1472 goto end;
1473 }
1474
1475 ret = lttng_dynamic_buffer_append(buffer,
1476 probe_function->function_name, function_name_len);
1477 if (ret) {
1478 goto end;
1479 }
1480 ret = lttng_dynamic_buffer_append(buffer,
1481 probe_function->binary_path, binary_path_len);
1482 if (ret) {
1483 goto end;
1484 }
1485
1486 /* Insert padding before the lookup method. */
1487 ret = lttng_dynamic_buffer_set_size(buffer,
1488 buffer->size + padding_needed);
1489 if (ret) {
1490 goto end;
1491 }
1492
1493 if (!location->lookup_method) {
1494 /* Not an error, the default method is used. */
1495 ret = storage_needed;
1496 goto end;
1497 }
1498
1499 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1500 flat_lookup_method.parent.type =
1501 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
1502 ret = lttng_dynamic_buffer_append(buffer,
1503 &flat_lookup_method, sizeof(flat_lookup_method));
1504 if (ret) {
1505 goto end;
1506 }
1507 ret = storage_needed;
1508end:
1509 return ret;
1510}
1511
f4d0bb2e
FD
1512static
1513int lttng_userspace_probe_location_tracepoint_flatten(
1514 const struct lttng_userspace_probe_location *location,
1515 struct lttng_dynamic_buffer *buffer)
1516{
1517 struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method;
1518 struct lttng_userspace_probe_location_tracepoint *probe_tracepoint;
1519 struct lttng_userspace_probe_location_tracepoint flat_probe;
1520 size_t probe_name_len, provider_name_len, binary_path_len;
1521 size_t padding_needed = 0;
1522 int storage_needed = 0;
1523 char *flat_probe_start;
1524 int ret = 0;
1525
1526 assert(location);
1527
1528 /* Only SDT tracepoints are supported at the moment */
1529 if (location->lookup_method && location->lookup_method->type !=
1530 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT) {
1531 ret = -LTTNG_ERR_INVALID;
1532 goto end;
1533 }
1534 probe_tracepoint = container_of(location,
1535 struct lttng_userspace_probe_location_tracepoint,
1536 parent);
1537 assert(probe_tracepoint->probe_name);
1538 assert(probe_tracepoint->provider_name);
1539 assert(probe_tracepoint->binary_path);
1540
1541 /* Compute the storage space needed to flatten the probe location */
1542 storage_needed += sizeof(struct lttng_userspace_probe_location_tracepoint);
1543
1544 probe_name_len = strlen(probe_tracepoint->probe_name) + 1;
1545 provider_name_len = strlen(probe_tracepoint->provider_name) + 1;
1546 binary_path_len = strlen(probe_tracepoint->binary_path) + 1;
1547
1548 storage_needed += probe_name_len + provider_name_len + binary_path_len;
1549
1550 /*
1551 * The lookup method is aligned to 64-bit within the buffer.
1552 * This is needed even if there is no lookup method since
1553 * the next structure in the buffer probably needs to be
1554 * aligned too (depending on the arch).
1555 */
1556 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1557 storage_needed += padding_needed;
1558
1559 if (location->lookup_method) {
1560 /* NOTE: elf look-up method is assumed here. */
1561 storage_needed +=
1562 sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1563 }
1564
1565 /*
1566 * If the caller set buffer to NULL, return the size of the needed buffer.
1567 */
1568 if (!buffer) {
1569 ret = storage_needed;
1570 goto end;
1571 }
1572
1573 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1574 ret = lttng_dynamic_buffer_set_capacity(buffer,
1575 buffer->size + storage_needed);
1576 if (ret) {
1577 goto end;
1578 }
1579 }
1580
1581 memset(&flat_probe, 0, sizeof(flat_probe));
1582
1583 flat_probe_start = buffer->data + buffer->size;
1584 flat_probe.parent.type = location->type;
1585
1586 /*
1587 * The lookup method, if present, is the last element in the flat
1588 * representation of the probe.
1589 */
1590 if (location->lookup_method) {
1591 flat_probe.parent.lookup_method =
1592 (struct lttng_userspace_probe_location_lookup_method *)
1593 (flat_probe_start + sizeof(flat_probe) +
1594 probe_name_len + provider_name_len +
1595 binary_path_len + padding_needed);
1596 } else {
1597 flat_probe.parent.lookup_method = NULL;
1598 }
1599
1600 flat_probe.probe_name = flat_probe_start + sizeof(flat_probe);
1601 flat_probe.provider_name = flat_probe.probe_name + probe_name_len;
1602 flat_probe.binary_path = flat_probe.provider_name + provider_name_len;
1603 flat_probe.binary_fd = -1;
1604 ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe));
1605 if (ret) {
1606 goto end;
1607 }
1608
1609 /* Append all the fields to the buffer */
1610 ret = lttng_dynamic_buffer_append(buffer,
1611 probe_tracepoint->probe_name, probe_name_len);
1612 if (ret) {
1613 goto end;
1614 }
1615 ret = lttng_dynamic_buffer_append(buffer,
1616 probe_tracepoint->provider_name, provider_name_len);
1617 if (ret) {
1618 goto end;
1619 }
1620 ret = lttng_dynamic_buffer_append(buffer,
1621 probe_tracepoint->binary_path, binary_path_len);
1622 if (ret) {
1623 goto end;
1624 }
1625
1626 /* Insert padding before the lookup method. */
1627 ret = lttng_dynamic_buffer_set_size(buffer, buffer->size + padding_needed);
1628 if (ret) {
1629 goto end;
1630 }
1631
1632 if (!location->lookup_method) {
1633 /* Not an error, the default method is used. */
1634 ret = storage_needed;
1635 goto end;
1636 }
1637
1638 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1639
1640 flat_lookup_method.parent.type =
1641 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
1642 ret = lttng_dynamic_buffer_append(buffer,
1643 &flat_lookup_method, sizeof(flat_lookup_method));
1644 if (ret) {
1645 goto end;
1646 }
1647 ret = storage_needed;
1648end:
1649 return ret;
1650}
1651
1ce46cfe
JG
1652LTTNG_HIDDEN
1653int lttng_userspace_probe_location_flatten(
1654 const struct lttng_userspace_probe_location *location,
1655 struct lttng_dynamic_buffer *buffer)
1656{
1657 int ret;
1658 if (!location) {
1659 ret = -LTTNG_ERR_INVALID;
1660 goto end;
1661 }
1662
1663 /* Only types currently supported. */
1664 switch (location->type) {
1665 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1666 ret = lttng_userspace_probe_location_function_flatten(location, buffer);
1667 break;
f4d0bb2e
FD
1668 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1669 ret = lttng_userspace_probe_location_tracepoint_flatten(location, buffer);
1670 break;
1ce46cfe
JG
1671 default:
1672 ret = -LTTNG_ERR_INVALID;
1673 goto end;
1674 }
1675
1676end:
1677 return ret;
1678}
394357fe
FD
1679
1680LTTNG_HIDDEN
1681struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
1682 const struct lttng_userspace_probe_location *location)
1683{
1684 struct lttng_userspace_probe_location *new_location = NULL;
1685 enum lttng_userspace_probe_location_type type;
1686
1687 if (!location) {
1688 goto err;
1689 }
1690
1691 type = lttng_userspace_probe_location_get_type(location);
1692 switch (type) {
1693 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1694 new_location =
1695 lttng_userspace_probe_location_function_copy(location);
1696 if (!new_location) {
1697 goto err;
1698 }
1699 break;
f4d0bb2e
FD
1700 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1701 new_location =
1702 lttng_userspace_probe_location_tracepoint_copy(location);
1703 if (!new_location) {
1704 goto err;
1705 }
1706 break;
394357fe
FD
1707 default:
1708 new_location = NULL;
1709 goto err;
1710 }
1711err:
1712 return new_location;
1713}
This page took 0.10094 seconds and 5 git commands to generate.