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