Cleanup: avoid duplicating userspace-probe desc twice
[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;
cc831309
FD
405 const char *binary_path = NULL;
406 const char *function_name = NULL;
394357fe
FD
407 int fd;
408
409 assert(location);
410 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
411
cc831309
FD
412 /* Get probe location fields */
413 binary_path = lttng_userspace_probe_location_function_get_binary_path(location);
394357fe 414 if (!binary_path) {
cc831309 415 ERR("Userspace probe binary path is NULL");
394357fe
FD
416 goto error;
417 }
418
cc831309 419 function_name = lttng_userspace_probe_location_function_get_function_name(location);
394357fe 420 if (!function_name) {
cc831309 421 ERR("Userspace probe function name is NULL");
394357fe
FD
422 goto error;
423 }
424
425 /* Duplicate the binary fd */
426 fd = dup(lttng_userspace_probe_location_function_get_binary_fd(location));
427 if (fd == -1) {
428 PERROR("Error duplicating file descriptor to binary");
429 goto error;
430 }
431
432 /*
433 * Duplicate probe location method fields
434 */
435 lookup_type = lttng_userspace_probe_location_lookup_method_get_type(
436 location->lookup_method);
437 switch (lookup_type) {
438 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
439 lookup_method =
440 lttng_userspace_probe_location_lookup_method_function_elf_copy(
441 location->lookup_method);
442 if (!lookup_method) {
443 goto close_fd;
444 }
445 break;
446 default:
447 /* Invalid probe location lookup method. */
448 goto close_fd;
449 }
450
451 /* Create the probe_location */
452 new_location = lttng_userspace_probe_location_function_create_no_check(
cc831309 453 binary_path, function_name, lookup_method, false);
394357fe
FD
454 if (!new_location) {
455 goto destroy_lookup_method;
456 }
457
458 /* Set the duplicated fd to the new probe_location */
459 if (lttng_userspace_probe_location_function_set_binary_fd(new_location, fd) < 0) {
460 goto destroy_probe_location;
461 }
462
463 goto end;
464
465destroy_probe_location:
466 lttng_userspace_probe_location_destroy(new_location);
467destroy_lookup_method:
468 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
469close_fd:
470 if (close(fd) < 0) {
471 PERROR("Error closing duplicated file descriptor in error path");
472 }
473error:
394357fe
FD
474 new_location = NULL;
475end:
476 return new_location;
477}
478
f4d0bb2e
FD
479static struct lttng_userspace_probe_location *
480lttng_userspace_probe_location_tracepoint_copy(
481 const struct lttng_userspace_probe_location *location)
482{
483 enum lttng_userspace_probe_location_lookup_method_type lookup_type;
484 struct lttng_userspace_probe_location *new_location = NULL;
485 struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
cc831309
FD
486 const char *binary_path = NULL;
487 const char *probe_name = NULL;
488 const char *provider_name = NULL;
f4d0bb2e
FD
489 int fd;
490
491 assert(location);
492 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
493
cc831309
FD
494 /* Get probe location fields */
495 binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(location);
f4d0bb2e 496 if (!binary_path) {
cc831309 497 ERR("Userspace probe binary path is NULL");
f4d0bb2e
FD
498 goto error;
499 }
500
cc831309 501 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(location);
f4d0bb2e 502 if (!probe_name) {
cc831309 503 ERR("Userspace probe probe name is NULL");
f4d0bb2e
FD
504 goto error;
505 }
506
cc831309 507 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(location);
f4d0bb2e 508 if (!provider_name) {
cc831309 509 ERR("Userspace probe provider name is NULL");
f4d0bb2e
FD
510 goto error;
511 }
512
513 /* Duplicate the binary fd */
514 fd = dup(lttng_userspace_probe_location_tracepoint_get_binary_fd(location));
515 if (fd == -1) {
cc831309 516 PERROR("Error duplicating file descriptor to binary");
f4d0bb2e
FD
517 goto error;
518 }
519
520 /*
521 * Duplicate probe location method fields
522 */
523 lookup_type = lttng_userspace_probe_location_lookup_method_get_type(
524 location->lookup_method);
525 switch (lookup_type) {
526 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
527 lookup_method =
528 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
529 location->lookup_method);
530 if (!lookup_method) {
531 goto close_fd;
532 }
533 break;
534 default:
535 /* Invalid probe location lookup method. */
536 goto close_fd;
537 }
538
539 /* Create the probe_location */
540 new_location = lttng_userspace_probe_location_tracepoint_create_no_check(
cc831309 541 binary_path, provider_name, probe_name, lookup_method, false);
f4d0bb2e
FD
542 if (!new_location) {
543 goto destroy_lookup_method;
544 }
545
546 /* Set the duplicated fd to the new probe_location */
547 if (lttng_userspace_probe_location_tracepoint_set_binary_fd(new_location, fd) < 0) {
548 goto destroy_probe_location;
549 }
550
551 goto end;
552
553destroy_probe_location:
554 lttng_userspace_probe_location_destroy(new_location);
555destroy_lookup_method:
556 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
557close_fd:
558 if (close(fd) < 0) {
cc831309 559 PERROR("Error closing duplicated file descriptor in error path");
f4d0bb2e
FD
560 }
561error:
f4d0bb2e
FD
562 new_location = NULL;
563end:
564 return new_location;
565}
566
1ce46cfe
JG
567const char *lttng_userspace_probe_location_function_get_binary_path(
568 const struct lttng_userspace_probe_location *location)
569{
570 const char *ret = NULL;
571 struct lttng_userspace_probe_location_function *function_location;
572
573 if (!location || lttng_userspace_probe_location_get_type(location) !=
574 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
575 ERR("Invalid argument(s)");
576 goto end;
577 }
578
579 function_location = container_of(location,
580 struct lttng_userspace_probe_location_function,
581 parent);
582 ret = function_location->binary_path;
583end:
584 return ret;
585}
586
f4d0bb2e
FD
587const char *lttng_userspace_probe_location_tracepoint_get_binary_path(
588 const struct lttng_userspace_probe_location *location)
589{
590 const char *ret = NULL;
591 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
592
593 if (!location || lttng_userspace_probe_location_get_type(location) !=
594 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
595 ERR("Invalid argument(s)");
596 goto end;
597 }
598
599 tracepoint_location = container_of(location,
600 struct lttng_userspace_probe_location_tracepoint,
601 parent);
602 ret = tracepoint_location->binary_path;
603end:
604 return ret;
605}
606
1ce46cfe
JG
607const char *lttng_userspace_probe_location_function_get_function_name(
608 const struct lttng_userspace_probe_location *location)
609{
610 const char *ret = NULL;
611 struct lttng_userspace_probe_location_function *function_location;
612
613 if (!location || lttng_userspace_probe_location_get_type(location) !=
614 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
615 ERR("Invalid argument(s)");
616 goto end;
617 }
618
619 function_location = container_of(location,
620 struct lttng_userspace_probe_location_function, parent);
621 ret = function_location->function_name;
622end:
623 return ret;
624}
625
f4d0bb2e
FD
626const char *lttng_userspace_probe_location_tracepoint_get_probe_name(
627 const struct lttng_userspace_probe_location *location)
628{
629 const char *ret = NULL;
630 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
631
632 if (!location || lttng_userspace_probe_location_get_type(location) !=
633 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
634 ERR("Invalid argument(s)");
635 goto end;
636 }
637
638 tracepoint_location = container_of(location,
639 struct lttng_userspace_probe_location_tracepoint, parent);
640 ret = tracepoint_location->probe_name;
641end:
642 return ret;
643}
644
645const char *lttng_userspace_probe_location_tracepoint_get_provider_name(
646 const struct lttng_userspace_probe_location *location)
647{
648 const char *ret = NULL;
649 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
650
651 if (!location || lttng_userspace_probe_location_get_type(location) !=
652 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
653 ERR("Invalid argument(s)");
654 goto end;
655 }
656
657 tracepoint_location = container_of(location,
658 struct lttng_userspace_probe_location_tracepoint, parent);
659 ret = tracepoint_location->provider_name;
660end:
661 return ret;
662}
663
1ce46cfe
JG
664int lttng_userspace_probe_location_function_get_binary_fd(
665 const struct lttng_userspace_probe_location *location)
666{
667 int ret = -1;
668 struct lttng_userspace_probe_location_function *function_location;
669
670 if (!location || lttng_userspace_probe_location_get_type(location) !=
671 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
672 ERR("Invalid argument(s)");
673 goto end;
674 }
675
676 function_location = container_of(location,
677 struct lttng_userspace_probe_location_function, parent);
678 ret = function_location->binary_fd;
679end:
680 return ret;
681}
682
9d3981b5
JG
683enum lttng_userspace_probe_location_function_instrumentation_type
684lttng_userspace_probe_location_function_get_instrumentation_type(
685 const struct lttng_userspace_probe_location *location)
686{
687 enum lttng_userspace_probe_location_function_instrumentation_type type;
688 struct lttng_userspace_probe_location_function *function_location;
689
690 if (!location || lttng_userspace_probe_location_get_type(location) !=
691 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
692 ERR("Invalid argument(s)");
693 type = LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_UNKNOWN;
694 goto end;
695 }
696
697 function_location = container_of(location,
698 struct lttng_userspace_probe_location_function, parent);
699 type = function_location->instrumentation_type;
700end:
701 return type;
702}
703
704enum lttng_userspace_probe_location_status
705lttng_userspace_probe_location_function_set_instrumentation_type(
706 const struct lttng_userspace_probe_location *location,
707 enum lttng_userspace_probe_location_function_instrumentation_type instrumentation_type)
708{
709 enum lttng_userspace_probe_location_status status =
710 LTTNG_USERSPACE_PROBE_LOCATION_STATUS_OK;
711 struct lttng_userspace_probe_location_function *function_location;
712
713 if (!location || lttng_userspace_probe_location_get_type(location) !=
714 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION ||
715 instrumentation_type !=
716 LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY) {
717 ERR("Invalid argument(s)");
718 status = LTTNG_USERSPACE_PROBE_LOCATION_STATUS_INVALID;
719 goto end;
720 }
721
722 function_location = container_of(location,
723 struct lttng_userspace_probe_location_function, parent);
724 function_location->instrumentation_type = instrumentation_type;
725end:
726 return status;
727}
728
f4d0bb2e
FD
729int lttng_userspace_probe_location_tracepoint_get_binary_fd(
730 const struct lttng_userspace_probe_location *location)
731{
732 int ret = -1;
733 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
734
735 if (!location || lttng_userspace_probe_location_get_type(location) !=
736 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
737 ERR("Invalid argument(s)");
738 goto end;
739 }
740
741 tracepoint_location = container_of(location,
742 struct lttng_userspace_probe_location_tracepoint, parent);
743 ret = tracepoint_location->binary_fd;
744end:
745 return ret;
746}
747
1ce46cfe
JG
748static struct lttng_userspace_probe_location_lookup_method *
749lttng_userspace_probe_location_function_get_lookup_method(
750 const struct lttng_userspace_probe_location *location)
751{
752 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
753
754 if (!location || lttng_userspace_probe_location_get_type(location) !=
755 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
756 ERR("Invalid argument(s)");
757 goto end;
758 }
759
760 ret = location->lookup_method;
761end:
762 return ret;
763}
764
f4d0bb2e
FD
765static struct lttng_userspace_probe_location_lookup_method *
766lttng_userspace_probe_location_tracepoint_get_lookup_method(
767 const struct lttng_userspace_probe_location *location)
768{
769 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
770
771 if (!location || lttng_userspace_probe_location_get_type(location) !=
772 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
773 ERR("Invalid argument(s)");
774 goto end;
775 }
776
777 ret = location->lookup_method;
778end:
779 return ret;
780}
781
87597c2c 782const struct lttng_userspace_probe_location_lookup_method *
1ce46cfe
JG
783lttng_userspace_probe_location_get_lookup_method(
784 const struct lttng_userspace_probe_location *location)
785{
786 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
787
788 assert(location);
789 switch (location->type) {
790 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
791 ret = lttng_userspace_probe_location_function_get_lookup_method(
792 location);
793 break;
f4d0bb2e
FD
794 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
795 ret = lttng_userspace_probe_location_tracepoint_get_lookup_method(
796 location);
797 break;
1ce46cfe
JG
798 default:
799 ERR("Unknowned lookup method.");
800 break;
801 }
802 return ret;
803}
804
805static
806int lttng_userspace_probe_location_lookup_method_serialize(
807 struct lttng_userspace_probe_location_lookup_method *method,
808 struct lttng_dynamic_buffer *buffer)
809{
810 int ret;
811 struct lttng_userspace_probe_location_lookup_method_comm
812 lookup_method_comm;
813
814 lookup_method_comm.type = (int8_t) (method ? method->type :
815 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT);
816 if (buffer) {
817 ret = lttng_dynamic_buffer_append(buffer, &lookup_method_comm,
818 sizeof(lookup_method_comm));
819 if (ret) {
820 goto end;
821 }
822 }
f4d0bb2e
FD
823 ret = sizeof(lookup_method_comm);
824end:
825 return ret;
826}
827
828static
829int lttng_userspace_probe_location_function_serialize(
830 const struct lttng_userspace_probe_location *location,
831 struct lttng_dynamic_buffer *buffer,
832 int *binary_fd)
833{
834 int ret;
835 size_t function_name_len, binary_path_len;
836 struct lttng_userspace_probe_location_function *location_function;
837 struct lttng_userspace_probe_location_function_comm location_function_comm;
838
839 assert(location);
840 assert(lttng_userspace_probe_location_get_type(location) ==
841 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
842
843 location_function = container_of(location,
844 struct lttng_userspace_probe_location_function,
845 parent);
846 if (!location_function->function_name || !location_function->binary_path) {
847 ret = -LTTNG_ERR_INVALID;
848 goto end;
849 }
850
851 if (binary_fd && location_function->binary_fd < 0) {
852 ret = -LTTNG_ERR_INVALID;
853 goto end;
854 }
855
856 if (binary_fd) {
857 *binary_fd = location_function->binary_fd;
858 }
859
860 function_name_len = strlen(location_function->function_name);
861 if (function_name_len == 0) {
862 ret = -LTTNG_ERR_INVALID;
863 goto end;
864 }
865 binary_path_len = strlen(location_function->binary_path);
866 if (binary_path_len == 0) {
867 ret = -LTTNG_ERR_INVALID;
868 goto end;
869 }
870
871 location_function_comm.function_name_len = function_name_len + 1;
872 location_function_comm.binary_path_len = binary_path_len + 1;
873
874 if (buffer) {
875 ret = lttng_dynamic_buffer_append(buffer,
876 &location_function_comm,
877 sizeof(location_function_comm));
878 if (ret) {
879 ret = -LTTNG_ERR_INVALID;
880 goto end;
881 }
882 ret = lttng_dynamic_buffer_append(buffer,
883 location_function->function_name,
884 location_function_comm.function_name_len);
885 if (ret) {
886 ret = -LTTNG_ERR_INVALID;
887 goto end;
888 }
889 ret = lttng_dynamic_buffer_append(buffer,
890 location_function->binary_path,
891 location_function_comm.binary_path_len);
892 if (ret) {
893 ret = -LTTNG_ERR_INVALID;
894 goto end;
895 }
896 }
897 ret = sizeof(location_function_comm) +
898 location_function_comm.function_name_len +
899 location_function_comm.binary_path_len;
1ce46cfe
JG
900end:
901 return ret;
902}
903
904static
f4d0bb2e 905int lttng_userspace_probe_location_tracepoint_serialize(
1ce46cfe
JG
906 const struct lttng_userspace_probe_location *location,
907 struct lttng_dynamic_buffer *buffer,
908 int *binary_fd)
909{
910 int ret;
f4d0bb2e
FD
911 size_t probe_name_len, provider_name_len, binary_path_len;
912 struct lttng_userspace_probe_location_tracepoint *location_tracepoint;
913 struct lttng_userspace_probe_location_tracepoint_comm location_tracepoint_comm;
1ce46cfe
JG
914
915 assert(location);
916 assert(lttng_userspace_probe_location_get_type(location) ==
f4d0bb2e 917 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1ce46cfe 918
f4d0bb2e
FD
919 location_tracepoint = container_of(location,
920 struct lttng_userspace_probe_location_tracepoint,
1ce46cfe 921 parent);
f4d0bb2e
FD
922 if (!location_tracepoint->probe_name ||
923 !location_tracepoint->provider_name ||
924 !location_tracepoint->binary_path) {
1ce46cfe
JG
925 ret = -LTTNG_ERR_INVALID;
926 goto end;
927 }
928
f4d0bb2e 929 if (binary_fd && location_tracepoint->binary_fd < 0) {
1ce46cfe
JG
930 ret = -LTTNG_ERR_INVALID;
931 goto end;
932 }
933
934 if (binary_fd) {
f4d0bb2e 935 *binary_fd = location_tracepoint->binary_fd;
1ce46cfe
JG
936 }
937
f4d0bb2e
FD
938 probe_name_len = strlen(location_tracepoint->probe_name);
939 if (probe_name_len == 0) {
1ce46cfe
JG
940 ret = -LTTNG_ERR_INVALID;
941 goto end;
942 }
f4d0bb2e
FD
943
944 provider_name_len = strlen(location_tracepoint->provider_name);
945 if (provider_name_len == 0) {
946 ret = -LTTNG_ERR_INVALID;
947 goto end;
948 }
949
950 binary_path_len = strlen(location_tracepoint->binary_path);
1ce46cfe
JG
951 if (binary_path_len == 0) {
952 ret = -LTTNG_ERR_INVALID;
953 goto end;
954 }
955
f4d0bb2e
FD
956 location_tracepoint_comm.probe_name_len = probe_name_len + 1;
957 location_tracepoint_comm.provider_name_len = provider_name_len + 1;
958 location_tracepoint_comm.binary_path_len = binary_path_len + 1;
1ce46cfe
JG
959
960 if (buffer) {
961 ret = lttng_dynamic_buffer_append(buffer,
f4d0bb2e
FD
962 &location_tracepoint_comm,
963 sizeof(location_tracepoint_comm));
1ce46cfe
JG
964 if (ret) {
965 ret = -LTTNG_ERR_INVALID;
966 goto end;
967 }
968 ret = lttng_dynamic_buffer_append(buffer,
f4d0bb2e
FD
969 location_tracepoint->probe_name,
970 location_tracepoint_comm.probe_name_len);
1ce46cfe
JG
971 if (ret) {
972 ret = -LTTNG_ERR_INVALID;
973 goto end;
974 }
975 ret = lttng_dynamic_buffer_append(buffer,
f4d0bb2e
FD
976 location_tracepoint->provider_name,
977 location_tracepoint_comm.provider_name_len);
978 if (ret) {
979 ret = -LTTNG_ERR_INVALID;
980 goto end;
981 }
982 ret = lttng_dynamic_buffer_append(buffer,
983 location_tracepoint->binary_path,
984 location_tracepoint_comm.binary_path_len);
1ce46cfe
JG
985 if (ret) {
986 ret = -LTTNG_ERR_INVALID;
987 goto end;
988 }
989 }
f4d0bb2e
FD
990 ret = sizeof(location_tracepoint_comm) +
991 location_tracepoint_comm.probe_name_len +
992 location_tracepoint_comm.provider_name_len +
993 location_tracepoint_comm.binary_path_len;
1ce46cfe
JG
994end:
995 return ret;
996}
997
998LTTNG_HIDDEN
999int lttng_userspace_probe_location_serialize(
1000 const struct lttng_userspace_probe_location *location,
1001 struct lttng_dynamic_buffer *buffer,
1002 int *binary_fd)
1003{
1004 int ret, buffer_use = 0;
1005 struct lttng_userspace_probe_location_comm location_generic_comm;
1006
1007 if (!location) {
1008 ERR("Invalid argument(s)");
1009 ret = -LTTNG_ERR_INVALID;
1010 goto end;
1011 }
1012
56f0bc67
JG
1013 memset(&location_generic_comm, 0, sizeof(location_generic_comm));
1014
1ce46cfe
JG
1015 location_generic_comm.type = (int8_t) location->type;
1016 if (buffer) {
1017 ret = lttng_dynamic_buffer_append(buffer, &location_generic_comm,
1018 sizeof(location_generic_comm));
1019 if (ret) {
1020 goto end;
1021 }
1022 }
1023 buffer_use += sizeof(location_generic_comm);
1024
1025 switch (lttng_userspace_probe_location_get_type(location)) {
1026 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1027 ret = lttng_userspace_probe_location_function_serialize(
1028 location, buffer, binary_fd);
1029 break;
f4d0bb2e
FD
1030 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1031 ret = lttng_userspace_probe_location_tracepoint_serialize(
1032 location, buffer, binary_fd);
1033 break;
1ce46cfe
JG
1034 default:
1035 ERR("Unsupported probe location type");
1036 ret = -LTTNG_ERR_INVALID;
1037 goto end;
1038 }
1039 if (ret < 0) {
1040 goto end;
1041 }
1042 buffer_use += ret;
1043
1044 ret = lttng_userspace_probe_location_lookup_method_serialize(
1045 location->lookup_method, buffer);
1046 if (ret < 0) {
1047 goto end;
1048 }
1049 ret += buffer_use;
1050end:
1051 return ret;
1052}
1053
1054static
1055int lttng_userspace_probe_location_function_create_from_buffer(
1056 const struct lttng_buffer_view *buffer,
1057 struct lttng_userspace_probe_location **location)
1058{
1059 struct lttng_userspace_probe_location_function_comm *location_function_comm;
1060 const char *function_name_src, *binary_path_src;
1061 char *function_name = NULL, *binary_path = NULL;
1062 int ret = 0;
1063
1064 assert(buffer);
1065 assert(buffer->data);
1066 assert(location);
1067
1068 location_function_comm =
1069 (struct lttng_userspace_probe_location_function_comm *) buffer->data;
1070
1071 const size_t expected_size = sizeof(*location_function_comm) +
1072 location_function_comm->function_name_len +
1073 location_function_comm->binary_path_len;
1074
1075 if (buffer->size < expected_size) {
1076 ret = -LTTNG_ERR_INVALID;
1077 goto end;
1078 }
1079
1080 function_name_src = buffer->data + sizeof(*location_function_comm);
1081 binary_path_src = function_name_src +
1082 location_function_comm->function_name_len;
1083
1084 if (function_name_src[location_function_comm->function_name_len - 1] != '\0') {
1085 ret = -LTTNG_ERR_INVALID;
1086 goto end;
1087 }
1088 if (binary_path_src[location_function_comm->binary_path_len - 1] != '\0') {
1089 ret = -LTTNG_ERR_INVALID;
1090 goto end;
1091 }
1092
1093 function_name = lttng_strndup(function_name_src, LTTNG_SYMBOL_NAME_LEN);
1094 if (!function_name) {
1095 PERROR("lttng_strndup");
1096 goto end;
1097 }
1098
1099 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1100 if (!binary_path) {
1101 PERROR("lttng_strndup");
1102 goto end;
1103 }
1104
1105 *location = lttng_userspace_probe_location_function_create_no_check(
1106 binary_path, function_name, NULL, false);
1107 if (!(*location)) {
1108 ret = -LTTNG_ERR_INVALID;
1109 goto end;
1110 }
1111
1112 ret = (int) expected_size;
1113end:
1114 free(function_name);
1115 free(binary_path);
1116 return ret;
1117}
1118
f4d0bb2e
FD
1119static
1120int lttng_userspace_probe_location_tracepoint_create_from_buffer(
1121 const struct lttng_buffer_view *buffer,
1122 struct lttng_userspace_probe_location **location)
1123{
1124 struct lttng_userspace_probe_location_tracepoint_comm *location_tracepoint_comm;
1125 const char *probe_name_src, *provider_name_src, *binary_path_src;
1126 char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
1127 int ret = 0;
1128
1129 assert(buffer);
1130 assert(buffer->data);
1131 assert(location);
1132
1133 location_tracepoint_comm =
1134 (struct lttng_userspace_probe_location_tracepoint_comm *) buffer->data;
1135
1136 const size_t expected_size = sizeof(*location_tracepoint_comm) +
1137 location_tracepoint_comm->probe_name_len +
1138 location_tracepoint_comm->provider_name_len +
1139 location_tracepoint_comm->binary_path_len;
1140
1141 if (buffer->size < expected_size) {
1142 ret = -LTTNG_ERR_INVALID;
1143 goto end;
1144 }
1145
1146 probe_name_src = buffer->data + sizeof(*location_tracepoint_comm);
1147 provider_name_src = probe_name_src +
1148 location_tracepoint_comm->probe_name_len;
1149 binary_path_src = provider_name_src +
1150 location_tracepoint_comm->provider_name_len;
1151
1152 if (probe_name_src[location_tracepoint_comm->probe_name_len - 1] != '\0') {
1153 ret = -LTTNG_ERR_INVALID;
1154 goto end;
1155 }
1156
1157 if (provider_name_src[location_tracepoint_comm->provider_name_len - 1] != '\0') {
1158 ret = -LTTNG_ERR_INVALID;
1159 goto end;
1160 }
1161
1162 if (binary_path_src[location_tracepoint_comm->binary_path_len - 1] != '\0') {
1163 ret = -LTTNG_ERR_INVALID;
1164 goto end;
1165 }
1166
1167 probe_name = lttng_strndup(probe_name_src, LTTNG_SYMBOL_NAME_LEN);
1168 if (!probe_name) {
1169 PERROR("lttng_strndup");
1170 goto end;
1171 }
1172 provider_name = lttng_strndup(provider_name_src, LTTNG_SYMBOL_NAME_LEN);
1173 if (!provider_name) {
1174 PERROR("lttng_strndup");
1175 goto end;
1176 }
1177
1178 binary_path = lttng_strndup(binary_path_src, LTTNG_SYMBOL_NAME_LEN);
1179 if (!binary_path) {
1180 PERROR("lttng_strndup");
1181 goto end;
1182 }
1183
1184 *location = lttng_userspace_probe_location_tracepoint_create_no_check(
1185 binary_path, provider_name, probe_name, NULL, false);
1186 if (!(*location)) {
1187 ret = -LTTNG_ERR_INVALID;
1188 goto end;
1189 }
1190
1191 ret = (int) expected_size;
1192end:
1193 free(probe_name);
1194 free(provider_name);
1195 free(binary_path);
1196 return ret;
1197}
1198
1ce46cfe
JG
1199static
1200int lttng_userspace_probe_location_lookup_method_create_from_buffer(
1201 struct lttng_buffer_view *buffer,
1202 struct lttng_userspace_probe_location_lookup_method **lookup_method)
1203{
1204 int ret;
1205 struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
1206 enum lttng_userspace_probe_location_lookup_method_type type;
1207
1208 assert(buffer);
1209 assert(buffer->data);
1210 assert(lookup_method);
1211
1212 if (buffer->size < sizeof(*lookup_comm)) {
1213 ret = -LTTNG_ERR_INVALID;
1214 goto end;
1215 }
1216
1217 lookup_comm = (struct lttng_userspace_probe_location_lookup_method_comm *)
1218 buffer->data;
1219 type = (enum lttng_userspace_probe_location_lookup_method_type)
1220 lookup_comm->type;
1221 switch (type) {
1222 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
1223 *lookup_method = NULL;
1224 break;
1225 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
1226 *lookup_method =
1227 lttng_userspace_probe_location_lookup_method_function_elf_create();
1228 if (!(*lookup_method)) {
1229 ret = -LTTNG_ERR_INVALID;
1230 goto end;
1231 }
1232 break;
f4d0bb2e
FD
1233 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
1234 *lookup_method =
1235 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1236 if (!(*lookup_method)) {
1237 ret = -LTTNG_ERR_INVALID;
1238 goto end;
1239 }
1240 break;
1ce46cfe
JG
1241 default:
1242 ret = -LTTNG_ERR_INVALID;
1243 goto end;
1244 }
1245
1246 ret = sizeof(*lookup_comm);
1247end:
1248 return ret;
1249}
1250
1251LTTNG_HIDDEN
1252int lttng_userspace_probe_location_create_from_buffer(
1253 const struct lttng_buffer_view *buffer,
1254 struct lttng_userspace_probe_location **location)
1255{
1256 struct lttng_userspace_probe_location_lookup_method *lookup_method;
1257 struct lttng_userspace_probe_location_comm *probe_location_comm;
1258 enum lttng_userspace_probe_location_type type;
1259 struct lttng_buffer_view lookup_method_view;
1260 int consumed = 0;
1261 int ret;
1262
1263
1264 assert(buffer);
1265 assert(buffer->data);
1266 assert(location);
1267
1268 lookup_method = NULL;
1269
1270 if (buffer->size <= sizeof(*probe_location_comm)) {
1271 ret = -LTTNG_ERR_INVALID;
1272 goto end;
1273 }
1274
1275 probe_location_comm =
1276 (struct lttng_userspace_probe_location_comm *) buffer->data;
1277 type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
1278 consumed += sizeof(*probe_location_comm);
1279
1280 switch (type) {
1281 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1282 {
1283 struct lttng_buffer_view view = lttng_buffer_view_from_view(
1284 buffer, consumed, buffer->size - consumed);
1285
1286 ret = lttng_userspace_probe_location_function_create_from_buffer(
1287 &view, location);
1288 if (ret < 0) {
1289 goto end;
1290 }
1291 break;
1292 }
f4d0bb2e
FD
1293 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1294 {
1295 struct lttng_buffer_view view = lttng_buffer_view_from_view(
1296 buffer, consumed, buffer->size - consumed);
1297
1298 ret = lttng_userspace_probe_location_tracepoint_create_from_buffer(
1299 &view, location);
1300 if (ret < 0) {
1301 goto end;
1302 }
1303 break;
1304 }
1ce46cfe
JG
1305 default:
1306 ret = -LTTNG_ERR_INVALID;
1307 goto end;
1308 }
1309
1310 consumed += ret;
1311 if (buffer->size <= consumed) {
1312 ret = -LTTNG_ERR_INVALID;
1313 goto end;
1314 }
1315
1316 lookup_method_view = lttng_buffer_view_from_view(buffer, consumed,
1317 buffer->size - consumed);
1318 ret = lttng_userspace_probe_location_lookup_method_create_from_buffer(
1319 &lookup_method_view, &lookup_method);
1320 if (ret < 0) {
1321 ret = -LTTNG_ERR_INVALID;
1322 goto end;
1323 }
1324
1325 assert(lookup_method);
1326 (*location)->lookup_method = lookup_method;
1327 lookup_method = NULL;
1328 ret += consumed;
1329end:
1330 return ret;
1331}
1332
1333LTTNG_HIDDEN
1334int lttng_userspace_probe_location_function_set_binary_fd(
1335 struct lttng_userspace_probe_location *location, int binary_fd)
1336{
1337 int ret = 0;
1338 struct lttng_userspace_probe_location_function *function_location;
1339
1340 assert(location);
1341 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1342
1343 function_location = container_of(location,
1344 struct lttng_userspace_probe_location_function, parent);
1345 if (function_location->binary_fd >= 0) {
1346 ret = close(function_location->binary_fd);
1347 if (ret) {
1348 PERROR("close");
1349 ret = -LTTNG_ERR_INVALID;
1350 goto end;
1351 }
1352 }
1353
1354 function_location->binary_fd = binary_fd;
1355end:
1356 return ret;
1357}
1358
f4d0bb2e
FD
1359LTTNG_HIDDEN
1360int lttng_userspace_probe_location_tracepoint_set_binary_fd(
1361 struct lttng_userspace_probe_location *location, int binary_fd)
1362{
1363 int ret = 0;
1364 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
1365
1366 assert(location);
1367 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1368
1369 tracepoint_location = container_of(location,
1370 struct lttng_userspace_probe_location_tracepoint, parent);
1371 if (tracepoint_location->binary_fd >= 0) {
1372 ret = close(tracepoint_location->binary_fd);
1373 if (ret) {
1374 PERROR("close");
1375 ret = -LTTNG_ERR_INVALID;
1376 goto end;
1377 }
1378 }
1379
1380 tracepoint_location->binary_fd = binary_fd;
1381end:
1382 return ret;
1383}
1384
1ce46cfe
JG
1385static
1386int lttng_userspace_probe_location_function_flatten(
1387 const struct lttng_userspace_probe_location *location,
1388 struct lttng_dynamic_buffer *buffer)
1389{
1390 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method;
1391 struct lttng_userspace_probe_location_function *probe_function;
1392 struct lttng_userspace_probe_location_function flat_probe;
1393 size_t function_name_len, binary_path_len;
1394 size_t padding_needed = 0;
1395 char *flat_probe_start;
1396 int storage_needed = 0;
1397 int ret;
1398
1399 assert(location);
1400
1401 if (location->lookup_method && location->lookup_method->type !=
1402 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF) {
1403 ret = -LTTNG_ERR_INVALID;
1404 goto end;
1405 }
1406
1407 probe_function = container_of(location,
1408 struct lttng_userspace_probe_location_function,
1409 parent);
1410 assert(probe_function->function_name);
1411 assert(probe_function->binary_path);
1412
1413 storage_needed +=
1414 sizeof(struct lttng_userspace_probe_location_function);
1415 function_name_len = strlen(probe_function->function_name) + 1;
1416 binary_path_len = strlen(probe_function->binary_path) + 1;
1417 storage_needed += function_name_len + binary_path_len;
1418
1419 /*
1420 * The lookup method is aligned to 64-bit within the buffer.
1421 * This is needed even if there is no lookup method since
1422 * the next structure in the buffer probably needs to be
1423 * aligned too (depending on the arch).
1424 */
1425 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1426 storage_needed += padding_needed;
1427
1428 if (location->lookup_method) {
1429 /* NOTE: elf look-up method is assumed here. */
1430 storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1431 }
1432
1433 if (!buffer) {
1434 ret = storage_needed;
1435 goto end;
1436 }
1437
1438 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1439 ret = lttng_dynamic_buffer_set_capacity(buffer,
1440 buffer->size + storage_needed);
1441 if (ret) {
1442 goto end;
1443 }
1444 }
1445
1446 memset(&flat_probe, 0, sizeof(flat_probe));
1447
1448 flat_probe_start = buffer->data + buffer->size;
1449 flat_probe.parent.type = location->type;
1450 /*
1451 * The lookup method, if present, is the last element in the flat
1452 * representation of the probe.
1453 */
1454 if (location->lookup_method) {
1455 flat_probe.parent.lookup_method =
1456 (struct lttng_userspace_probe_location_lookup_method *)
1457 (flat_probe_start + sizeof(flat_probe) +
1458 function_name_len + binary_path_len + padding_needed);
1459 } else {
1460 flat_probe.parent.lookup_method = NULL;
1461 }
1462
1463 flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
1464 flat_probe.binary_path = flat_probe.function_name + function_name_len;
1465 flat_probe.binary_fd = -1;
1466 ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
1467 sizeof(flat_probe));
1468 if (ret) {
1469 goto end;
1470 }
1471
1472 ret = lttng_dynamic_buffer_append(buffer,
1473 probe_function->function_name, function_name_len);
1474 if (ret) {
1475 goto end;
1476 }
1477 ret = lttng_dynamic_buffer_append(buffer,
1478 probe_function->binary_path, binary_path_len);
1479 if (ret) {
1480 goto end;
1481 }
1482
1483 /* Insert padding before the lookup method. */
1484 ret = lttng_dynamic_buffer_set_size(buffer,
1485 buffer->size + padding_needed);
1486 if (ret) {
1487 goto end;
1488 }
1489
1490 if (!location->lookup_method) {
1491 /* Not an error, the default method is used. */
1492 ret = storage_needed;
1493 goto end;
1494 }
1495
1496 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1497 flat_lookup_method.parent.type =
1498 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
1499 ret = lttng_dynamic_buffer_append(buffer,
1500 &flat_lookup_method, sizeof(flat_lookup_method));
1501 if (ret) {
1502 goto end;
1503 }
1504 ret = storage_needed;
1505end:
1506 return ret;
1507}
1508
f4d0bb2e
FD
1509static
1510int lttng_userspace_probe_location_tracepoint_flatten(
1511 const struct lttng_userspace_probe_location *location,
1512 struct lttng_dynamic_buffer *buffer)
1513{
1514 struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method;
1515 struct lttng_userspace_probe_location_tracepoint *probe_tracepoint;
1516 struct lttng_userspace_probe_location_tracepoint flat_probe;
1517 size_t probe_name_len, provider_name_len, binary_path_len;
1518 size_t padding_needed = 0;
1519 int storage_needed = 0;
1520 char *flat_probe_start;
1521 int ret = 0;
1522
1523 assert(location);
1524
1525 /* Only SDT tracepoints are supported at the moment */
1526 if (location->lookup_method && location->lookup_method->type !=
1527 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT) {
1528 ret = -LTTNG_ERR_INVALID;
1529 goto end;
1530 }
1531 probe_tracepoint = container_of(location,
1532 struct lttng_userspace_probe_location_tracepoint,
1533 parent);
1534 assert(probe_tracepoint->probe_name);
1535 assert(probe_tracepoint->provider_name);
1536 assert(probe_tracepoint->binary_path);
1537
1538 /* Compute the storage space needed to flatten the probe location */
1539 storage_needed += sizeof(struct lttng_userspace_probe_location_tracepoint);
1540
1541 probe_name_len = strlen(probe_tracepoint->probe_name) + 1;
1542 provider_name_len = strlen(probe_tracepoint->provider_name) + 1;
1543 binary_path_len = strlen(probe_tracepoint->binary_path) + 1;
1544
1545 storage_needed += probe_name_len + provider_name_len + binary_path_len;
1546
1547 /*
1548 * The lookup method is aligned to 64-bit within the buffer.
1549 * This is needed even if there is no lookup method since
1550 * the next structure in the buffer probably needs to be
1551 * aligned too (depending on the arch).
1552 */
1553 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1554 storage_needed += padding_needed;
1555
1556 if (location->lookup_method) {
1557 /* NOTE: elf look-up method is assumed here. */
1558 storage_needed +=
1559 sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1560 }
1561
1562 /*
1563 * If the caller set buffer to NULL, return the size of the needed buffer.
1564 */
1565 if (!buffer) {
1566 ret = storage_needed;
1567 goto end;
1568 }
1569
1570 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1571 ret = lttng_dynamic_buffer_set_capacity(buffer,
1572 buffer->size + storage_needed);
1573 if (ret) {
1574 goto end;
1575 }
1576 }
1577
1578 memset(&flat_probe, 0, sizeof(flat_probe));
1579
1580 flat_probe_start = buffer->data + buffer->size;
1581 flat_probe.parent.type = location->type;
1582
1583 /*
1584 * The lookup method, if present, is the last element in the flat
1585 * representation of the probe.
1586 */
1587 if (location->lookup_method) {
1588 flat_probe.parent.lookup_method =
1589 (struct lttng_userspace_probe_location_lookup_method *)
1590 (flat_probe_start + sizeof(flat_probe) +
1591 probe_name_len + provider_name_len +
1592 binary_path_len + padding_needed);
1593 } else {
1594 flat_probe.parent.lookup_method = NULL;
1595 }
1596
1597 flat_probe.probe_name = flat_probe_start + sizeof(flat_probe);
1598 flat_probe.provider_name = flat_probe.probe_name + probe_name_len;
1599 flat_probe.binary_path = flat_probe.provider_name + provider_name_len;
1600 flat_probe.binary_fd = -1;
1601 ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe));
1602 if (ret) {
1603 goto end;
1604 }
1605
1606 /* Append all the fields to the buffer */
1607 ret = lttng_dynamic_buffer_append(buffer,
1608 probe_tracepoint->probe_name, probe_name_len);
1609 if (ret) {
1610 goto end;
1611 }
1612 ret = lttng_dynamic_buffer_append(buffer,
1613 probe_tracepoint->provider_name, provider_name_len);
1614 if (ret) {
1615 goto end;
1616 }
1617 ret = lttng_dynamic_buffer_append(buffer,
1618 probe_tracepoint->binary_path, binary_path_len);
1619 if (ret) {
1620 goto end;
1621 }
1622
1623 /* Insert padding before the lookup method. */
1624 ret = lttng_dynamic_buffer_set_size(buffer, buffer->size + padding_needed);
1625 if (ret) {
1626 goto end;
1627 }
1628
1629 if (!location->lookup_method) {
1630 /* Not an error, the default method is used. */
1631 ret = storage_needed;
1632 goto end;
1633 }
1634
1635 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1636
1637 flat_lookup_method.parent.type =
1638 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
1639 ret = lttng_dynamic_buffer_append(buffer,
1640 &flat_lookup_method, sizeof(flat_lookup_method));
1641 if (ret) {
1642 goto end;
1643 }
1644 ret = storage_needed;
1645end:
1646 return ret;
1647}
1648
1ce46cfe
JG
1649LTTNG_HIDDEN
1650int lttng_userspace_probe_location_flatten(
1651 const struct lttng_userspace_probe_location *location,
1652 struct lttng_dynamic_buffer *buffer)
1653{
1654 int ret;
1655 if (!location) {
1656 ret = -LTTNG_ERR_INVALID;
1657 goto end;
1658 }
1659
1660 /* Only types currently supported. */
1661 switch (location->type) {
1662 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1663 ret = lttng_userspace_probe_location_function_flatten(location, buffer);
1664 break;
f4d0bb2e
FD
1665 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1666 ret = lttng_userspace_probe_location_tracepoint_flatten(location, buffer);
1667 break;
1ce46cfe
JG
1668 default:
1669 ret = -LTTNG_ERR_INVALID;
1670 goto end;
1671 }
1672
1673end:
1674 return ret;
1675}
394357fe
FD
1676
1677LTTNG_HIDDEN
1678struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
1679 const struct lttng_userspace_probe_location *location)
1680{
1681 struct lttng_userspace_probe_location *new_location = NULL;
1682 enum lttng_userspace_probe_location_type type;
1683
1684 if (!location) {
1685 goto err;
1686 }
1687
1688 type = lttng_userspace_probe_location_get_type(location);
1689 switch (type) {
1690 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1691 new_location =
1692 lttng_userspace_probe_location_function_copy(location);
1693 if (!new_location) {
1694 goto err;
1695 }
1696 break;
f4d0bb2e
FD
1697 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1698 new_location =
1699 lttng_userspace_probe_location_tracepoint_copy(location);
1700 if (!new_location) {
1701 goto err;
1702 }
1703 break;
394357fe
FD
1704 default:
1705 new_location = NULL;
1706 goto err;
1707 }
1708err:
1709 return new_location;
1710}
This page took 0.087521 seconds and 4 git commands to generate.