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