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