MI: implement all objects related to trigger machine interface
[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
e368fb43 8#include "lttng/lttng-error.h"
1ce46cfe 9#include <assert.h>
dfcfa983 10#include <common/compat/string.h>
1ce46cfe 11#include <common/error.h>
959e3c66
JR
12#include <common/hashtable/hashtable.h>
13#include <common/hashtable/utils.h>
6a751b95
JR
14#include <common/macros.h>
15#include <common/mi-lttng.h>
16#include <common/payload-view.h>
17#include <common/payload.h>
1ce46cfe
JG
18#include <fcntl.h>
19#include <lttng/constant.h>
20#include <lttng/userspace-probe-internal.h>
dfcfa983
JR
21#include <sys/stat.h>
22#include <sys/types.h>
23#include <sys/unistd.h>
1ce46cfe 24
fe489250 25static
2cde0510 26int lttng_userspace_probe_location_function_set_binary_fd_handle(
fe489250 27 struct lttng_userspace_probe_location *location,
2cde0510 28 struct fd_handle *binary_fd_handle);
fe489250
JG
29
30static
2cde0510 31int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
fe489250 32 struct lttng_userspace_probe_location *location,
2cde0510 33 struct fd_handle *binary_fd_handle);
fe489250 34
6a751b95
JR
35static
36enum lttng_error_code lttng_userspace_probe_location_lookup_method_mi_serialize(
37 const struct lttng_userspace_probe_location_lookup_method
38 *method,
39 struct mi_writer *writer);
40
41static
42enum lttng_error_code lttng_userspace_probe_location_tracepoint_mi_serialize(
43 const struct lttng_userspace_probe_location *location,
44 struct mi_writer *writer);
45
46static
47enum lttng_error_code lttng_userspace_probe_location_function_mi_serialize(
48 const struct lttng_userspace_probe_location *location,
49 struct mi_writer *writer);
50
1ce46cfe
JG
51enum lttng_userspace_probe_location_lookup_method_type
52lttng_userspace_probe_location_lookup_method_get_type(
53 const struct lttng_userspace_probe_location_lookup_method *lookup_method)
54{
55 return lookup_method ? lookup_method->type :
56 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_UNKNOWN;
57}
58
59void lttng_userspace_probe_location_lookup_method_destroy(
60 struct lttng_userspace_probe_location_lookup_method *lookup_method)
61{
62 if (!lookup_method){
63 return;
64 }
65
5d21f143 66 free(lookup_method);
1ce46cfe
JG
67}
68
69struct lttng_userspace_probe_location_lookup_method *
70lttng_userspace_probe_location_lookup_method_function_elf_create(void)
71{
72 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
73 struct lttng_userspace_probe_location_lookup_method_elf *elf_method;
74
75 elf_method = zmalloc(sizeof(*elf_method));
76 if (!elf_method) {
77 PERROR("zmalloc");
78 goto end;
79 }
80
81 ret = &elf_method->parent;
82 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
83end:
84 return ret;
85}
86
f4d0bb2e
FD
87struct lttng_userspace_probe_location_lookup_method *
88lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create(void)
89{
90 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
91 struct lttng_userspace_probe_location_lookup_method_sdt *sdt_method;
92
93 sdt_method = zmalloc(sizeof(*sdt_method));
94 if (!sdt_method) {
95 PERROR("zmalloc");
96 goto end;
97 }
98
99 ret = &sdt_method->parent;
100 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
101end:
102 return ret;
103}
104
1ce46cfe
JG
105enum lttng_userspace_probe_location_type lttng_userspace_probe_location_get_type(
106 const struct lttng_userspace_probe_location *location)
107{
108 return location ? location->type :
109 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN;
110}
111
112static
113void lttng_userspace_probe_location_function_destroy(
114 struct lttng_userspace_probe_location *location)
115{
116 struct lttng_userspace_probe_location_function *location_function = NULL;
117
118 assert(location);
119
120 location_function = container_of(location,
121 struct lttng_userspace_probe_location_function, parent);
122
123 assert(location_function);
124
125 free(location_function->function_name);
126 free(location_function->binary_path);
2cde0510 127 fd_handle_put(location_function->binary_fd_handle);
1ce46cfe
JG
128 free(location);
129}
130
f4d0bb2e
FD
131static
132void lttng_userspace_probe_location_tracepoint_destroy(
133 struct lttng_userspace_probe_location *location)
134{
135 struct lttng_userspace_probe_location_tracepoint *location_tracepoint = NULL;
136
137 assert(location);
138
139 location_tracepoint = container_of(location,
140 struct lttng_userspace_probe_location_tracepoint,
141 parent);
142
143 assert(location_tracepoint);
144
145 free(location_tracepoint->probe_name);
146 free(location_tracepoint->provider_name);
147 free(location_tracepoint->binary_path);
2cde0510 148 fd_handle_put(location_tracepoint->binary_fd_handle);
f4d0bb2e
FD
149 free(location);
150}
151
1ce46cfe
JG
152void lttng_userspace_probe_location_destroy(
153 struct lttng_userspace_probe_location *location)
154{
155 if (!location) {
156 return;
157 }
158
159 lttng_userspace_probe_location_lookup_method_destroy(
160 location->lookup_method);
161
162 switch (location->type) {
163 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
164 lttng_userspace_probe_location_function_destroy(location);
165 break;
f4d0bb2e
FD
166 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
167 lttng_userspace_probe_location_tracepoint_destroy(location);
168 break;
1ce46cfe 169 default:
adf53c67 170 abort();
1ce46cfe
JG
171 }
172}
173
dfcfa983
JR
174/* Compare two file descriptors based on their inode and device numbers. */
175static bool fd_is_equal(int a, int b)
176{
177 int ret;
178 bool is_equal = false;
179 struct stat a_stat, b_stat;
180
181 if (a < 0 && b >= 0) {
182 goto end;
183 }
184
185 if (b < 0 && a >= 0) {
186 goto end;
187 }
188
189 if (a < 0 && b < 0) {
190 if (a == -1 && b == -1) {
191 is_equal = true;
192 goto end;
193 }
194
195 /* Invalid state, abort. */
196 abort();
197 }
198
199 /* Both are valid file descriptors. */
200 ret = fstat(a, &a_stat);
201 if (ret) {
202 PERROR("Failed to fstat userspace probe location binary fd %d",
203 a);
204 goto end;
205 }
206
207 ret = fstat(b, &b_stat);
208 if (ret) {
209 PERROR("Failed to fstat userspace probe location binary fd %d",
210 b);
211 goto end;
212 }
213
214 is_equal = (a_stat.st_ino == b_stat.st_ino) &&
215 (a_stat.st_dev == b_stat.st_dev);
216
217end:
218 return is_equal;
219}
220
959e3c66
JR
221static unsigned long lttng_userspace_probe_location_function_hash(
222 const struct lttng_userspace_probe_location *location)
223{
224 unsigned long hash = hash_key_ulong(
225 (void *) LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION,
226 lttng_ht_seed);
227 struct lttng_userspace_probe_location_function *function_location =
228 container_of(location, typeof(*function_location),
229 parent);
230
231 hash ^= hash_key_str(function_location->function_name, lttng_ht_seed);
232 hash ^= hash_key_str(function_location->binary_path, lttng_ht_seed);
233 /*
234 * No need to hash on the fd. Worst comes to worse,
235 * the equal function will discriminate.
236 */
237 return hash;
238}
239
dfcfa983
JR
240static bool lttng_userspace_probe_location_function_is_equal(
241 const struct lttng_userspace_probe_location *_a,
242 const struct lttng_userspace_probe_location *_b)
243{
244 bool is_equal = false;
245 struct lttng_userspace_probe_location_function *a, *b;
246
247 a = container_of(_a, struct lttng_userspace_probe_location_function,
248 parent);
249 b = container_of(_b, struct lttng_userspace_probe_location_function,
250 parent);
251
252 if (a->instrumentation_type != b->instrumentation_type) {
253 goto end;
254 }
255
256 assert(a->function_name);
257 assert(b->function_name);
258 if (strcmp(a->function_name, b->function_name)) {
259 goto end;
260 }
261
262 assert(a->binary_path);
263 assert(b->binary_path);
264 if (strcmp(a->binary_path, b->binary_path)) {
265 goto end;
266 }
267
2cde0510
JG
268 is_equal = fd_is_equal(a->binary_fd_handle ? fd_handle_get_fd(a->binary_fd_handle) : -1,
269 b->binary_fd_handle ? fd_handle_get_fd(b->binary_fd_handle) : -1);
dfcfa983
JR
270end:
271 return is_equal;
272}
273
1ce46cfe
JG
274static struct lttng_userspace_probe_location *
275lttng_userspace_probe_location_function_create_no_check(const char *binary_path,
276 const char *function_name,
277 struct lttng_userspace_probe_location_lookup_method *lookup_method,
278 bool open_binary)
279{
280 int binary_fd = -1;
fe489250 281 struct fd_handle *binary_fd_handle = NULL;
1ce46cfe
JG
282 char *function_name_copy = NULL, *binary_path_copy = NULL;
283 struct lttng_userspace_probe_location *ret = NULL;
284 struct lttng_userspace_probe_location_function *location;
285
286 if (open_binary) {
287 binary_fd = open(binary_path, O_RDONLY);
288 if (binary_fd < 0) {
289 PERROR("Error opening the binary");
290 goto error;
291 }
fe489250
JG
292
293 binary_fd_handle = fd_handle_create(binary_fd);
294 if (!binary_fd) {
295 goto error;
296 }
297
298 /* Ownership transferred to fd_handle. */
1ce46cfe
JG
299 binary_fd = -1;
300 }
301
302 function_name_copy = lttng_strndup(function_name, LTTNG_SYMBOL_NAME_LEN);
303 if (!function_name_copy) {
304 PERROR("Error duplicating the function name");
305 goto error;
306 }
307
308 binary_path_copy = lttng_strndup(binary_path, LTTNG_PATH_MAX);
309 if (!binary_path_copy) {
310 PERROR("Error duplicating the function name");
311 goto error;
312 }
313
314 location = zmalloc(sizeof(*location));
315 if (!location) {
316 PERROR("Error allocating userspace probe location");
317 goto error;
318 }
319
320 location->function_name = function_name_copy;
321 location->binary_path = binary_path_copy;
2cde0510 322 location->binary_fd_handle = binary_fd_handle;
fe489250 323 binary_fd_handle = NULL;
9d3981b5
JG
324 location->instrumentation_type =
325 LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY;
1ce46cfe
JG
326
327 ret = &location->parent;
328 ret->lookup_method = lookup_method;
329 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION;
dfcfa983 330 ret->equal = lttng_userspace_probe_location_function_is_equal;
959e3c66 331 ret->hash = lttng_userspace_probe_location_function_hash;
1ce46cfe
JG
332 goto end;
333
334error:
335 free(function_name_copy);
336 free(binary_path_copy);
337 if (binary_fd >= 0) {
338 if (close(binary_fd)) {
339 PERROR("Error closing binary fd in error path");
340 }
341 }
fe489250 342 fd_handle_put(binary_fd_handle);
1ce46cfe
JG
343end:
344 return ret;
345}
346
959e3c66
JR
347static unsigned long lttng_userspace_probe_location_tracepoint_hash(
348 const struct lttng_userspace_probe_location *location)
349{
350 unsigned long hash = hash_key_ulong(
351 (void *) LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT,
352 lttng_ht_seed);
353 struct lttng_userspace_probe_location_tracepoint *tp_location =
354 container_of(location, typeof(*tp_location), parent);
355
356 hash ^= hash_key_str(tp_location->probe_name, lttng_ht_seed);
357 hash ^= hash_key_str(tp_location->provider_name, lttng_ht_seed);
358 hash ^= hash_key_str(tp_location->binary_path, lttng_ht_seed);
359 /*
360 * No need to hash on the fd. Worst comes to worse,
361 * the equal function will discriminate.
362 */
363 return hash;
364}
365
dfcfa983
JR
366static bool lttng_userspace_probe_location_tracepoint_is_equal(
367 const struct lttng_userspace_probe_location *_a,
368 const struct lttng_userspace_probe_location *_b)
369{
370 bool is_equal = false;
371 struct lttng_userspace_probe_location_tracepoint *a, *b;
372
373 a = container_of(_a, struct lttng_userspace_probe_location_tracepoint,
374 parent);
375 b = container_of(_b, struct lttng_userspace_probe_location_tracepoint,
376 parent);
377
378 assert(a->probe_name);
379 assert(b->probe_name);
380 if (strcmp(a->probe_name, b->probe_name)) {
381 goto end;
382 }
383
384 assert(a->provider_name);
385 assert(b->provider_name);
386 if (strcmp(a->provider_name, b->provider_name)) {
387 goto end;
388 }
389
390 assert(a->binary_path);
391 assert(b->binary_path);
392 if (strcmp(a->binary_path, b->binary_path)) {
393 goto end;
394 }
395
2cde0510
JG
396 is_equal = fd_is_equal(a->binary_fd_handle ? fd_handle_get_fd(a->binary_fd_handle) : -1,
397 b->binary_fd_handle ? fd_handle_get_fd(b->binary_fd_handle) : -1);
dfcfa983
JR
398
399end:
400 return is_equal;
401}
402
f4d0bb2e
FD
403static struct lttng_userspace_probe_location *
404lttng_userspace_probe_location_tracepoint_create_no_check(const char *binary_path,
405 const char *provider_name, const char *probe_name,
406 struct lttng_userspace_probe_location_lookup_method *lookup_method,
407 bool open_binary)
408{
409 int binary_fd = -1;
fe489250 410 struct fd_handle *binary_fd_handle = NULL;
f4d0bb2e
FD
411 char *probe_name_copy = NULL;
412 char *provider_name_copy = NULL;
413 char *binary_path_copy = NULL;
414 struct lttng_userspace_probe_location *ret = NULL;
415 struct lttng_userspace_probe_location_tracepoint *location;
416
417 if (open_binary) {
418 binary_fd = open(binary_path, O_RDONLY);
419 if (binary_fd < 0) {
420 PERROR("open");
421 goto error;
422 }
fe489250
JG
423
424 binary_fd_handle = fd_handle_create(binary_fd);
425 if (!binary_fd) {
426 goto error;
427 }
428
429 /* Ownership transferred to fd_handle. */
f4d0bb2e
FD
430 binary_fd = -1;
431 }
432
433 probe_name_copy = lttng_strndup(probe_name, LTTNG_SYMBOL_NAME_LEN);
434 if (!probe_name_copy) {
435 PERROR("lttng_strndup");
436 goto error;
437 }
438
439 provider_name_copy = lttng_strndup(provider_name, LTTNG_SYMBOL_NAME_LEN);
440 if (!provider_name_copy) {
441 PERROR("lttng_strndup");
442 goto error;
443 }
444
445 binary_path_copy = lttng_strndup(binary_path, LTTNG_PATH_MAX);
446 if (!binary_path_copy) {
447 PERROR("lttng_strndup");
448 goto error;
449 }
450
451 location = zmalloc(sizeof(*location));
452 if (!location) {
453 PERROR("zmalloc");
454 goto error;
455 }
456
457 location->probe_name = probe_name_copy;
458 location->provider_name = provider_name_copy;
459 location->binary_path = binary_path_copy;
2cde0510 460 location->binary_fd_handle = binary_fd_handle;
fe489250 461 binary_fd_handle = NULL;
f4d0bb2e
FD
462
463 ret = &location->parent;
464 ret->lookup_method = lookup_method;
465 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT;
dfcfa983 466 ret->equal = lttng_userspace_probe_location_tracepoint_is_equal;
959e3c66 467 ret->hash = lttng_userspace_probe_location_tracepoint_hash;
f4d0bb2e
FD
468 goto end;
469
470error:
471 free(probe_name_copy);
472 free(provider_name_copy);
7c86453b 473 free(binary_path_copy);
f4d0bb2e
FD
474 if (binary_fd >= 0) {
475 if (close(binary_fd)) {
476 PERROR("Error closing binary fd in error path");
477 }
478 }
fe489250 479 fd_handle_put(binary_fd_handle);
f4d0bb2e
FD
480end:
481 return ret;
482}
483
1ce46cfe
JG
484struct lttng_userspace_probe_location *
485lttng_userspace_probe_location_function_create(const char *binary_path,
486 const char *function_name,
487 struct lttng_userspace_probe_location_lookup_method *lookup_method)
488{
489 struct lttng_userspace_probe_location *ret = NULL;
490
491 if (!binary_path || !function_name) {
f04a8200 492 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
1ce46cfe
JG
493 goto end;
494 }
495
496 switch (lttng_userspace_probe_location_lookup_method_get_type(
497 lookup_method)) {
498 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
499 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
500 break;
501 default:
502 /* Invalid probe location lookup method. */
503 goto end;
504 }
505
506 ret = lttng_userspace_probe_location_function_create_no_check(
507 binary_path, function_name, lookup_method, true);
508end:
509 return ret;
510}
511
f4d0bb2e
FD
512struct lttng_userspace_probe_location *
513lttng_userspace_probe_location_tracepoint_create(const char *binary_path,
514 const char *provider_name, const char *probe_name,
515 struct lttng_userspace_probe_location_lookup_method *lookup_method)
516{
517 struct lttng_userspace_probe_location *ret = NULL;
518
519 if (!binary_path || !probe_name || !provider_name) {
f04a8200 520 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
f4d0bb2e
FD
521 goto end;
522 }
523
524 switch (lttng_userspace_probe_location_lookup_method_get_type(
525 lookup_method)) {
526 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
527 break;
528 default:
529 /* Invalid probe location lookup method. */
530 goto end;
531 }
532
533 ret = lttng_userspace_probe_location_tracepoint_create_no_check(
534 binary_path, provider_name, probe_name, lookup_method, true);
535end:
536 return ret;
537}
538
394357fe
FD
539static struct lttng_userspace_probe_location_lookup_method *
540lttng_userspace_probe_location_lookup_method_function_elf_copy(
541 const struct lttng_userspace_probe_location_lookup_method *lookup_method)
542{
543 struct lttng_userspace_probe_location_lookup_method *parent = NULL;
544 struct lttng_userspace_probe_location_lookup_method_elf *elf_method;
545
546 assert(lookup_method);
547 assert(lookup_method->type ==
548 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF);
549
550 elf_method = zmalloc(sizeof(*elf_method));
551 if (!elf_method) {
552 PERROR("Error allocating ELF userspace probe lookup method");
553 goto error;
554 }
555
556 elf_method->parent.type = lookup_method->type;
557 parent = &elf_method->parent;
558
559 goto end;
560error:
561 parent = NULL;
562end:
563 return parent;
564}
565
f4d0bb2e
FD
566static struct lttng_userspace_probe_location_lookup_method *
567lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
568 struct lttng_userspace_probe_location_lookup_method *lookup_method)
569{
570 struct lttng_userspace_probe_location_lookup_method *parent = NULL;
571 struct lttng_userspace_probe_location_lookup_method_sdt *sdt_method;
572
573 assert(lookup_method);
574 assert(lookup_method->type ==
575 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT);
576
577 sdt_method = zmalloc(sizeof(*sdt_method));
578 if (!sdt_method) {
579 PERROR("zmalloc");
580 goto error;
581 }
582
583 sdt_method->parent.type = lookup_method->type;
584 parent = &sdt_method->parent;
585
586 goto end;
587
588error:
589 parent = NULL;
590end:
591 return parent;
592}
593
394357fe
FD
594static struct lttng_userspace_probe_location *
595lttng_userspace_probe_location_function_copy(
596 const struct lttng_userspace_probe_location *location)
597{
598 enum lttng_userspace_probe_location_lookup_method_type lookup_type;
599 struct lttng_userspace_probe_location *new_location = NULL;
600 struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
cc831309
FD
601 const char *binary_path = NULL;
602 const char *function_name = NULL;
fe489250 603 struct lttng_userspace_probe_location_function *function_location;
394357fe
FD
604
605 assert(location);
606 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
fe489250
JG
607 function_location = container_of(
608 location, typeof(*function_location), parent);
394357fe 609
cc831309
FD
610 /* Get probe location fields */
611 binary_path = lttng_userspace_probe_location_function_get_binary_path(location);
394357fe 612 if (!binary_path) {
cc831309 613 ERR("Userspace probe binary path is NULL");
394357fe
FD
614 goto error;
615 }
616
cc831309 617 function_name = lttng_userspace_probe_location_function_get_function_name(location);
394357fe 618 if (!function_name) {
cc831309 619 ERR("Userspace probe function name is NULL");
394357fe
FD
620 goto error;
621 }
622
394357fe
FD
623 /*
624 * Duplicate probe location method fields
625 */
626 lookup_type = lttng_userspace_probe_location_lookup_method_get_type(
627 location->lookup_method);
628 switch (lookup_type) {
629 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
630 lookup_method =
631 lttng_userspace_probe_location_lookup_method_function_elf_copy(
632 location->lookup_method);
633 if (!lookup_method) {
fe489250 634 goto error;
394357fe
FD
635 }
636 break;
637 default:
638 /* Invalid probe location lookup method. */
fe489250 639 goto error;
394357fe
FD
640 }
641
642 /* Create the probe_location */
643 new_location = lttng_userspace_probe_location_function_create_no_check(
cc831309 644 binary_path, function_name, lookup_method, false);
394357fe
FD
645 if (!new_location) {
646 goto destroy_lookup_method;
647 }
648
649 /* Set the duplicated fd to the new probe_location */
2cde0510
JG
650 if (lttng_userspace_probe_location_function_set_binary_fd_handle(new_location,
651 function_location->binary_fd_handle) < 0) {
394357fe
FD
652 goto destroy_probe_location;
653 }
654
655 goto end;
656
657destroy_probe_location:
658 lttng_userspace_probe_location_destroy(new_location);
659destroy_lookup_method:
660 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
394357fe 661error:
394357fe
FD
662 new_location = NULL;
663end:
664 return new_location;
665}
666
f4d0bb2e
FD
667static struct lttng_userspace_probe_location *
668lttng_userspace_probe_location_tracepoint_copy(
669 const struct lttng_userspace_probe_location *location)
670{
671 enum lttng_userspace_probe_location_lookup_method_type lookup_type;
672 struct lttng_userspace_probe_location *new_location = NULL;
673 struct lttng_userspace_probe_location_lookup_method *lookup_method = NULL;
cc831309
FD
674 const char *binary_path = NULL;
675 const char *probe_name = NULL;
676 const char *provider_name = NULL;
fe489250 677 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
f4d0bb2e
FD
678
679 assert(location);
680 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
fe489250
JG
681 tracepoint_location = container_of(
682 location, typeof(*tracepoint_location), parent);
f4d0bb2e 683
fe489250 684 /* Get probe location fields */
cc831309 685 binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(location);
f4d0bb2e 686 if (!binary_path) {
cc831309 687 ERR("Userspace probe binary path is NULL");
f4d0bb2e
FD
688 goto error;
689 }
690
cc831309 691 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(location);
f4d0bb2e 692 if (!probe_name) {
cc831309 693 ERR("Userspace probe probe name is NULL");
f4d0bb2e
FD
694 goto error;
695 }
696
cc831309 697 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(location);
f4d0bb2e 698 if (!provider_name) {
cc831309 699 ERR("Userspace probe provider name is NULL");
f4d0bb2e
FD
700 goto error;
701 }
702
f4d0bb2e
FD
703 /*
704 * Duplicate probe location method fields
705 */
706 lookup_type = lttng_userspace_probe_location_lookup_method_get_type(
707 location->lookup_method);
708 switch (lookup_type) {
709 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
710 lookup_method =
711 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_copy(
712 location->lookup_method);
713 if (!lookup_method) {
fe489250 714 goto error;
f4d0bb2e
FD
715 }
716 break;
717 default:
718 /* Invalid probe location lookup method. */
fe489250 719 goto error;
f4d0bb2e
FD
720 }
721
722 /* Create the probe_location */
723 new_location = lttng_userspace_probe_location_tracepoint_create_no_check(
cc831309 724 binary_path, provider_name, probe_name, lookup_method, false);
f4d0bb2e
FD
725 if (!new_location) {
726 goto destroy_lookup_method;
727 }
728
729 /* Set the duplicated fd to the new probe_location */
2cde0510
JG
730 if (lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(new_location,
731 tracepoint_location->binary_fd_handle) < 0) {
f4d0bb2e
FD
732 goto destroy_probe_location;
733 }
734
735 goto end;
736
737destroy_probe_location:
738 lttng_userspace_probe_location_destroy(new_location);
739destroy_lookup_method:
740 lttng_userspace_probe_location_lookup_method_destroy(lookup_method);
f4d0bb2e 741error:
f4d0bb2e
FD
742 new_location = NULL;
743end:
744 return new_location;
745}
746
1ce46cfe
JG
747const char *lttng_userspace_probe_location_function_get_binary_path(
748 const struct lttng_userspace_probe_location *location)
749{
750 const char *ret = NULL;
751 struct lttng_userspace_probe_location_function *function_location;
752
753 if (!location || lttng_userspace_probe_location_get_type(location) !=
754 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
f04a8200 755 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
1ce46cfe
JG
756 goto end;
757 }
758
759 function_location = container_of(location,
760 struct lttng_userspace_probe_location_function,
761 parent);
762 ret = function_location->binary_path;
763end:
764 return ret;
765}
766
f4d0bb2e
FD
767const char *lttng_userspace_probe_location_tracepoint_get_binary_path(
768 const struct lttng_userspace_probe_location *location)
769{
770 const char *ret = NULL;
771 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
772
773 if (!location || lttng_userspace_probe_location_get_type(location) !=
774 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
f04a8200 775 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
f4d0bb2e
FD
776 goto end;
777 }
778
779 tracepoint_location = container_of(location,
780 struct lttng_userspace_probe_location_tracepoint,
781 parent);
782 ret = tracepoint_location->binary_path;
783end:
784 return ret;
785}
786
1ce46cfe
JG
787const char *lttng_userspace_probe_location_function_get_function_name(
788 const struct lttng_userspace_probe_location *location)
789{
790 const char *ret = NULL;
791 struct lttng_userspace_probe_location_function *function_location;
792
793 if (!location || lttng_userspace_probe_location_get_type(location) !=
794 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
f04a8200 795 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
1ce46cfe
JG
796 goto end;
797 }
798
799 function_location = container_of(location,
800 struct lttng_userspace_probe_location_function, parent);
801 ret = function_location->function_name;
802end:
803 return ret;
804}
805
f4d0bb2e
FD
806const char *lttng_userspace_probe_location_tracepoint_get_probe_name(
807 const struct lttng_userspace_probe_location *location)
808{
809 const char *ret = NULL;
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) {
f04a8200 814 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
f4d0bb2e
FD
815 goto end;
816 }
817
818 tracepoint_location = container_of(location,
819 struct lttng_userspace_probe_location_tracepoint, parent);
820 ret = tracepoint_location->probe_name;
821end:
822 return ret;
823}
824
825const char *lttng_userspace_probe_location_tracepoint_get_provider_name(
826 const struct lttng_userspace_probe_location *location)
827{
828 const char *ret = NULL;
829 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
830
831 if (!location || lttng_userspace_probe_location_get_type(location) !=
832 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
f04a8200 833 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
f4d0bb2e
FD
834 goto end;
835 }
836
837 tracepoint_location = container_of(location,
838 struct lttng_userspace_probe_location_tracepoint, parent);
839 ret = tracepoint_location->provider_name;
840end:
841 return ret;
842}
843
1ce46cfe
JG
844int lttng_userspace_probe_location_function_get_binary_fd(
845 const struct lttng_userspace_probe_location *location)
846{
847 int ret = -1;
848 struct lttng_userspace_probe_location_function *function_location;
849
850 if (!location || lttng_userspace_probe_location_get_type(location) !=
851 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
f04a8200 852 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
1ce46cfe
JG
853 goto end;
854 }
855
856 function_location = container_of(location,
857 struct lttng_userspace_probe_location_function, parent);
2cde0510
JG
858 ret = function_location->binary_fd_handle ?
859 fd_handle_get_fd(function_location->binary_fd_handle) : -1;
1ce46cfe
JG
860end:
861 return ret;
862}
863
9d3981b5
JG
864enum lttng_userspace_probe_location_function_instrumentation_type
865lttng_userspace_probe_location_function_get_instrumentation_type(
866 const struct lttng_userspace_probe_location *location)
867{
868 enum lttng_userspace_probe_location_function_instrumentation_type type;
869 struct lttng_userspace_probe_location_function *function_location;
870
871 if (!location || lttng_userspace_probe_location_get_type(location) !=
872 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
f04a8200 873 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
9d3981b5
JG
874 type = LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_UNKNOWN;
875 goto end;
876 }
877
878 function_location = container_of(location,
879 struct lttng_userspace_probe_location_function, parent);
880 type = function_location->instrumentation_type;
881end:
882 return type;
883}
884
885enum lttng_userspace_probe_location_status
886lttng_userspace_probe_location_function_set_instrumentation_type(
887 const struct lttng_userspace_probe_location *location,
888 enum lttng_userspace_probe_location_function_instrumentation_type instrumentation_type)
889{
890 enum lttng_userspace_probe_location_status status =
891 LTTNG_USERSPACE_PROBE_LOCATION_STATUS_OK;
892 struct lttng_userspace_probe_location_function *function_location;
893
894 if (!location || lttng_userspace_probe_location_get_type(location) !=
895 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION ||
896 instrumentation_type !=
897 LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY) {
f04a8200 898 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
9d3981b5
JG
899 status = LTTNG_USERSPACE_PROBE_LOCATION_STATUS_INVALID;
900 goto end;
901 }
902
903 function_location = container_of(location,
904 struct lttng_userspace_probe_location_function, parent);
905 function_location->instrumentation_type = instrumentation_type;
906end:
907 return status;
908}
909
f4d0bb2e
FD
910int lttng_userspace_probe_location_tracepoint_get_binary_fd(
911 const struct lttng_userspace_probe_location *location)
912{
913 int ret = -1;
914 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
915
916 if (!location || lttng_userspace_probe_location_get_type(location) !=
917 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
f04a8200 918 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
f4d0bb2e
FD
919 goto end;
920 }
921
922 tracepoint_location = container_of(location,
923 struct lttng_userspace_probe_location_tracepoint, parent);
2cde0510
JG
924 ret = tracepoint_location->binary_fd_handle ?
925 fd_handle_get_fd(tracepoint_location->binary_fd_handle) : -1;
f4d0bb2e
FD
926end:
927 return ret;
928}
929
1ce46cfe
JG
930static struct lttng_userspace_probe_location_lookup_method *
931lttng_userspace_probe_location_function_get_lookup_method(
932 const struct lttng_userspace_probe_location *location)
933{
934 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
935
936 if (!location || lttng_userspace_probe_location_get_type(location) !=
937 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
f04a8200 938 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
1ce46cfe
JG
939 goto end;
940 }
941
942 ret = location->lookup_method;
943end:
944 return ret;
945}
946
f4d0bb2e
FD
947static struct lttng_userspace_probe_location_lookup_method *
948lttng_userspace_probe_location_tracepoint_get_lookup_method(
949 const struct lttng_userspace_probe_location *location)
950{
951 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
952
953 if (!location || lttng_userspace_probe_location_get_type(location) !=
954 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
f04a8200 955 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
f4d0bb2e
FD
956 goto end;
957 }
958
959 ret = location->lookup_method;
960end:
961 return ret;
962}
963
87597c2c 964const struct lttng_userspace_probe_location_lookup_method *
1ce46cfe
JG
965lttng_userspace_probe_location_get_lookup_method(
966 const struct lttng_userspace_probe_location *location)
967{
968 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
969
970 assert(location);
971 switch (location->type) {
972 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
973 ret = lttng_userspace_probe_location_function_get_lookup_method(
974 location);
975 break;
f4d0bb2e
FD
976 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
977 ret = lttng_userspace_probe_location_tracepoint_get_lookup_method(
978 location);
979 break;
1ce46cfe
JG
980 default:
981 ERR("Unknowned lookup method.");
982 break;
983 }
984 return ret;
985}
986
987static
988int lttng_userspace_probe_location_lookup_method_serialize(
989 struct lttng_userspace_probe_location_lookup_method *method,
e368fb43 990 struct lttng_payload *payload)
1ce46cfe
JG
991{
992 int ret;
993 struct lttng_userspace_probe_location_lookup_method_comm
994 lookup_method_comm;
995
996 lookup_method_comm.type = (int8_t) (method ? method->type :
997 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT);
e368fb43
JG
998 if (payload) {
999 ret = lttng_dynamic_buffer_append(&payload->buffer, &lookup_method_comm,
1ce46cfe
JG
1000 sizeof(lookup_method_comm));
1001 if (ret) {
1002 goto end;
1003 }
1004 }
f4d0bb2e
FD
1005 ret = sizeof(lookup_method_comm);
1006end:
1007 return ret;
1008}
1009
1010static
1011int lttng_userspace_probe_location_function_serialize(
1012 const struct lttng_userspace_probe_location *location,
e368fb43 1013 struct lttng_payload *payload)
f4d0bb2e
FD
1014{
1015 int ret;
1016 size_t function_name_len, binary_path_len;
1017 struct lttng_userspace_probe_location_function *location_function;
1018 struct lttng_userspace_probe_location_function_comm location_function_comm;
1019
1020 assert(location);
1021 assert(lttng_userspace_probe_location_get_type(location) ==
1022 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1023
1024 location_function = container_of(location,
1025 struct lttng_userspace_probe_location_function,
1026 parent);
1027 if (!location_function->function_name || !location_function->binary_path) {
1028 ret = -LTTNG_ERR_INVALID;
1029 goto end;
1030 }
1031
2cde0510 1032 if (payload && !location_function->binary_fd_handle) {
f4d0bb2e
FD
1033 ret = -LTTNG_ERR_INVALID;
1034 goto end;
1035 }
1036
f4d0bb2e
FD
1037 function_name_len = strlen(location_function->function_name);
1038 if (function_name_len == 0) {
1039 ret = -LTTNG_ERR_INVALID;
1040 goto end;
1041 }
1042 binary_path_len = strlen(location_function->binary_path);
1043 if (binary_path_len == 0) {
1044 ret = -LTTNG_ERR_INVALID;
1045 goto end;
1046 }
1047
1048 location_function_comm.function_name_len = function_name_len + 1;
1049 location_function_comm.binary_path_len = binary_path_len + 1;
1050
e368fb43
JG
1051 if (payload) {
1052 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1053 &location_function_comm,
1054 sizeof(location_function_comm));
1055 if (ret) {
1056 ret = -LTTNG_ERR_INVALID;
1057 goto end;
1058 }
e368fb43 1059 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1060 location_function->function_name,
1061 location_function_comm.function_name_len);
1062 if (ret) {
1063 ret = -LTTNG_ERR_INVALID;
1064 goto end;
1065 }
e368fb43 1066 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1067 location_function->binary_path,
1068 location_function_comm.binary_path_len);
1069 if (ret) {
1070 ret = -LTTNG_ERR_INVALID;
1071 goto end;
1072 }
fe489250 1073 ret = lttng_payload_push_fd_handle(
2cde0510 1074 payload, location_function->binary_fd_handle);
e368fb43
JG
1075 if (ret) {
1076 ret = -LTTNG_ERR_INVALID;
1077 goto end;
1078 }
f4d0bb2e
FD
1079 }
1080 ret = sizeof(location_function_comm) +
1081 location_function_comm.function_name_len +
1082 location_function_comm.binary_path_len;
1ce46cfe
JG
1083end:
1084 return ret;
1085}
1086
1087static
f4d0bb2e 1088int lttng_userspace_probe_location_tracepoint_serialize(
1ce46cfe 1089 const struct lttng_userspace_probe_location *location,
e368fb43 1090 struct lttng_payload *payload)
1ce46cfe
JG
1091{
1092 int ret;
f4d0bb2e
FD
1093 size_t probe_name_len, provider_name_len, binary_path_len;
1094 struct lttng_userspace_probe_location_tracepoint *location_tracepoint;
1095 struct lttng_userspace_probe_location_tracepoint_comm location_tracepoint_comm;
1ce46cfe
JG
1096
1097 assert(location);
1098 assert(lttng_userspace_probe_location_get_type(location) ==
f4d0bb2e 1099 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1ce46cfe 1100
f4d0bb2e
FD
1101 location_tracepoint = container_of(location,
1102 struct lttng_userspace_probe_location_tracepoint,
1ce46cfe 1103 parent);
f4d0bb2e
FD
1104 if (!location_tracepoint->probe_name ||
1105 !location_tracepoint->provider_name ||
1106 !location_tracepoint->binary_path) {
1ce46cfe
JG
1107 ret = -LTTNG_ERR_INVALID;
1108 goto end;
1109 }
1110
2cde0510 1111 if (payload && !location_tracepoint->binary_fd_handle) {
1ce46cfe
JG
1112 ret = -LTTNG_ERR_INVALID;
1113 goto end;
1114 }
1115
f4d0bb2e
FD
1116 probe_name_len = strlen(location_tracepoint->probe_name);
1117 if (probe_name_len == 0) {
1ce46cfe
JG
1118 ret = -LTTNG_ERR_INVALID;
1119 goto end;
1120 }
f4d0bb2e
FD
1121
1122 provider_name_len = strlen(location_tracepoint->provider_name);
1123 if (provider_name_len == 0) {
1124 ret = -LTTNG_ERR_INVALID;
1125 goto end;
1126 }
1127
1128 binary_path_len = strlen(location_tracepoint->binary_path);
1ce46cfe
JG
1129 if (binary_path_len == 0) {
1130 ret = -LTTNG_ERR_INVALID;
1131 goto end;
1132 }
1133
f4d0bb2e
FD
1134 location_tracepoint_comm.probe_name_len = probe_name_len + 1;
1135 location_tracepoint_comm.provider_name_len = provider_name_len + 1;
1136 location_tracepoint_comm.binary_path_len = binary_path_len + 1;
1ce46cfe 1137
e368fb43
JG
1138 if (payload) {
1139 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1140 &location_tracepoint_comm,
1141 sizeof(location_tracepoint_comm));
1ce46cfe
JG
1142 if (ret) {
1143 ret = -LTTNG_ERR_INVALID;
1144 goto end;
1145 }
e368fb43 1146 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1147 location_tracepoint->probe_name,
1148 location_tracepoint_comm.probe_name_len);
1ce46cfe
JG
1149 if (ret) {
1150 ret = -LTTNG_ERR_INVALID;
1151 goto end;
1152 }
e368fb43 1153 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1154 location_tracepoint->provider_name,
1155 location_tracepoint_comm.provider_name_len);
1156 if (ret) {
1157 ret = -LTTNG_ERR_INVALID;
1158 goto end;
1159 }
e368fb43 1160 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1161 location_tracepoint->binary_path,
1162 location_tracepoint_comm.binary_path_len);
1ce46cfe
JG
1163 if (ret) {
1164 ret = -LTTNG_ERR_INVALID;
1165 goto end;
1166 }
fe489250 1167 ret = lttng_payload_push_fd_handle(
2cde0510 1168 payload, location_tracepoint->binary_fd_handle);
e368fb43
JG
1169 if (ret) {
1170 ret = -LTTNG_ERR_INVALID;
1171 goto end;
1172 }
1ce46cfe 1173 }
e368fb43 1174
f4d0bb2e
FD
1175 ret = sizeof(location_tracepoint_comm) +
1176 location_tracepoint_comm.probe_name_len +
1177 location_tracepoint_comm.provider_name_len +
1178 location_tracepoint_comm.binary_path_len;
1ce46cfe
JG
1179end:
1180 return ret;
1181}
1182
1183LTTNG_HIDDEN
1184int lttng_userspace_probe_location_serialize(
1185 const struct lttng_userspace_probe_location *location,
e368fb43 1186 struct lttng_payload *payload)
1ce46cfe
JG
1187{
1188 int ret, buffer_use = 0;
1189 struct lttng_userspace_probe_location_comm location_generic_comm;
1190
1191 if (!location) {
f04a8200 1192 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
1ce46cfe
JG
1193 ret = -LTTNG_ERR_INVALID;
1194 goto end;
1195 }
1196
56f0bc67
JG
1197 memset(&location_generic_comm, 0, sizeof(location_generic_comm));
1198
1ce46cfe 1199 location_generic_comm.type = (int8_t) location->type;
e368fb43
JG
1200 if (payload) {
1201 ret = lttng_dynamic_buffer_append(&payload->buffer,
1202 &location_generic_comm,
1ce46cfe
JG
1203 sizeof(location_generic_comm));
1204 if (ret) {
1205 goto end;
1206 }
1207 }
1208 buffer_use += sizeof(location_generic_comm);
1209
1210 switch (lttng_userspace_probe_location_get_type(location)) {
1211 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1212 ret = lttng_userspace_probe_location_function_serialize(
e368fb43 1213 location, payload);
1ce46cfe 1214 break;
f4d0bb2e
FD
1215 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1216 ret = lttng_userspace_probe_location_tracepoint_serialize(
e368fb43 1217 location, payload);
f4d0bb2e 1218 break;
1ce46cfe
JG
1219 default:
1220 ERR("Unsupported probe location type");
1221 ret = -LTTNG_ERR_INVALID;
1222 goto end;
1223 }
1224 if (ret < 0) {
1225 goto end;
1226 }
1227 buffer_use += ret;
1228
1229 ret = lttng_userspace_probe_location_lookup_method_serialize(
e368fb43 1230 location->lookup_method, payload);
1ce46cfe
JG
1231 if (ret < 0) {
1232 goto end;
1233 }
1234 ret += buffer_use;
1235end:
1236 return ret;
1237}
1238
1239static
e368fb43
JG
1240int lttng_userspace_probe_location_function_create_from_payload(
1241 struct lttng_payload_view *view,
1ce46cfe
JG
1242 struct lttng_userspace_probe_location **location)
1243{
1244 struct lttng_userspace_probe_location_function_comm *location_function_comm;
1245 const char *function_name_src, *binary_path_src;
1246 char *function_name = NULL, *binary_path = NULL;
1247 int ret = 0;
e368fb43 1248 size_t expected_size;
2cde0510 1249 struct fd_handle *binary_fd_handle = lttng_payload_view_pop_fd_handle(view);
1ce46cfe 1250
1ce46cfe
JG
1251 assert(location);
1252
e368fb43
JG
1253 if (view->buffer.size < sizeof(*location_function_comm)) {
1254 ret = -LTTNG_ERR_INVALID;
1255 goto end;
1256 }
1257
1ce46cfe 1258 location_function_comm =
e368fb43 1259 (typeof(location_function_comm)) view->buffer.data;
1ce46cfe 1260
e368fb43 1261 expected_size = sizeof(*location_function_comm) +
1ce46cfe
JG
1262 location_function_comm->function_name_len +
1263 location_function_comm->binary_path_len;
1264
e368fb43 1265 if (view->buffer.size < expected_size) {
1ce46cfe
JG
1266 ret = -LTTNG_ERR_INVALID;
1267 goto end;
1268 }
1269
e368fb43 1270 function_name_src = view->buffer.data + sizeof(*location_function_comm);
1ce46cfe
JG
1271 binary_path_src = function_name_src +
1272 location_function_comm->function_name_len;
1273
48c24aea
JG
1274 if (!lttng_buffer_view_contains_string(&view->buffer, function_name_src,
1275 location_function_comm->function_name_len)) {
1ce46cfe
JG
1276 ret = -LTTNG_ERR_INVALID;
1277 goto end;
1278 }
48c24aea
JG
1279
1280 if (!lttng_buffer_view_contains_string(&view->buffer, binary_path_src,
1281 location_function_comm->binary_path_len)) {
1ce46cfe
JG
1282 ret = -LTTNG_ERR_INVALID;
1283 goto end;
1284 }
1285
1286 function_name = lttng_strndup(function_name_src, LTTNG_SYMBOL_NAME_LEN);
1287 if (!function_name) {
1288 PERROR("lttng_strndup");
2aa28610 1289 ret = -LTTNG_ERR_NOMEM;
1ce46cfe
JG
1290 goto end;
1291 }
1292
1293 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1294 if (!binary_path) {
1295 PERROR("lttng_strndup");
2aa28610 1296 ret = -LTTNG_ERR_NOMEM;
1ce46cfe
JG
1297 goto end;
1298 }
1299
1300 *location = lttng_userspace_probe_location_function_create_no_check(
1301 binary_path, function_name, NULL, false);
1302 if (!(*location)) {
1303 ret = -LTTNG_ERR_INVALID;
1304 goto end;
1305 }
1306
2cde0510
JG
1307 ret = lttng_userspace_probe_location_function_set_binary_fd_handle(
1308 *location, binary_fd_handle);
e368fb43 1309 if (ret) {
e368fb43
JG
1310 ret = -LTTNG_ERR_INVALID;
1311 goto end;
1312 }
1313
1ce46cfe
JG
1314 ret = (int) expected_size;
1315end:
2cde0510 1316 fd_handle_put(binary_fd_handle);
1ce46cfe
JG
1317 free(function_name);
1318 free(binary_path);
1319 return ret;
1320}
1321
f4d0bb2e 1322static
e368fb43
JG
1323int lttng_userspace_probe_location_tracepoint_create_from_payload(
1324 struct lttng_payload_view *view,
f4d0bb2e
FD
1325 struct lttng_userspace_probe_location **location)
1326{
1327 struct lttng_userspace_probe_location_tracepoint_comm *location_tracepoint_comm;
1328 const char *probe_name_src, *provider_name_src, *binary_path_src;
1329 char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
1330 int ret = 0;
e368fb43 1331 size_t expected_size;
2cde0510 1332 struct fd_handle *binary_fd_handle = lttng_payload_view_pop_fd_handle(view);
f4d0bb2e 1333
f4d0bb2e
FD
1334 assert(location);
1335
2cde0510 1336 if (!binary_fd_handle) {
e368fb43
JG
1337 ret = -LTTNG_ERR_INVALID;
1338 goto end;
1339 }
1340
1341 if (view->buffer.size < sizeof(*location_tracepoint_comm)) {
1342 ret = -LTTNG_ERR_INVALID;
1343 goto end;
1344 }
1345
f4d0bb2e 1346 location_tracepoint_comm =
e368fb43 1347 (typeof(location_tracepoint_comm)) view->buffer.data;
f4d0bb2e 1348
e368fb43 1349 expected_size = sizeof(*location_tracepoint_comm) +
f4d0bb2e
FD
1350 location_tracepoint_comm->probe_name_len +
1351 location_tracepoint_comm->provider_name_len +
1352 location_tracepoint_comm->binary_path_len;
1353
e368fb43 1354 if (view->buffer.size < expected_size) {
f4d0bb2e
FD
1355 ret = -LTTNG_ERR_INVALID;
1356 goto end;
1357 }
1358
e368fb43 1359 probe_name_src = view->buffer.data + sizeof(*location_tracepoint_comm);
f4d0bb2e
FD
1360 provider_name_src = probe_name_src +
1361 location_tracepoint_comm->probe_name_len;
1362 binary_path_src = provider_name_src +
1363 location_tracepoint_comm->provider_name_len;
1364
48c24aea
JG
1365 if (!lttng_buffer_view_contains_string(&view->buffer, probe_name_src,
1366 location_tracepoint_comm->probe_name_len)) {
f4d0bb2e
FD
1367 ret = -LTTNG_ERR_INVALID;
1368 goto end;
1369 }
1370
48c24aea
JG
1371 if (!lttng_buffer_view_contains_string(&view->buffer, provider_name_src,
1372 location_tracepoint_comm->provider_name_len)) {
f4d0bb2e
FD
1373 ret = -LTTNG_ERR_INVALID;
1374 goto end;
1375 }
1376
48c24aea
JG
1377 if (!lttng_buffer_view_contains_string(&view->buffer, binary_path_src,
1378 location_tracepoint_comm->binary_path_len)) {
f4d0bb2e
FD
1379 ret = -LTTNG_ERR_INVALID;
1380 goto end;
1381 }
1382
1383 probe_name = lttng_strndup(probe_name_src, LTTNG_SYMBOL_NAME_LEN);
1384 if (!probe_name) {
1385 PERROR("lttng_strndup");
1386 goto end;
1387 }
1388 provider_name = lttng_strndup(provider_name_src, LTTNG_SYMBOL_NAME_LEN);
1389 if (!provider_name) {
1390 PERROR("lttng_strndup");
1391 goto end;
1392 }
1393
1394 binary_path = lttng_strndup(binary_path_src, LTTNG_SYMBOL_NAME_LEN);
1395 if (!binary_path) {
1396 PERROR("lttng_strndup");
1397 goto end;
1398 }
1399
1400 *location = lttng_userspace_probe_location_tracepoint_create_no_check(
1401 binary_path, provider_name, probe_name, NULL, false);
1402 if (!(*location)) {
1403 ret = -LTTNG_ERR_INVALID;
1404 goto end;
1405 }
1406
2cde0510
JG
1407 ret = lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
1408 *location, binary_fd_handle);
e368fb43 1409 if (ret) {
e368fb43
JG
1410 ret = -LTTNG_ERR_INVALID;
1411 goto end;
1412 }
1413
f4d0bb2e
FD
1414 ret = (int) expected_size;
1415end:
2cde0510 1416 fd_handle_put(binary_fd_handle);
f4d0bb2e
FD
1417 free(probe_name);
1418 free(provider_name);
1419 free(binary_path);
1420 return ret;
1421}
1422
1ce46cfe 1423static
e368fb43
JG
1424int lttng_userspace_probe_location_lookup_method_create_from_payload(
1425 struct lttng_payload_view *view,
1ce46cfe
JG
1426 struct lttng_userspace_probe_location_lookup_method **lookup_method)
1427{
1428 int ret;
1429 struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
1430 enum lttng_userspace_probe_location_lookup_method_type type;
1431
e368fb43 1432 assert(view);
1ce46cfe
JG
1433 assert(lookup_method);
1434
e368fb43 1435 if (view->buffer.size < sizeof(*lookup_comm)) {
1ce46cfe
JG
1436 ret = -LTTNG_ERR_INVALID;
1437 goto end;
1438 }
1439
e368fb43 1440 lookup_comm = (typeof(lookup_comm)) view->buffer.data;
1ce46cfe
JG
1441 type = (enum lttng_userspace_probe_location_lookup_method_type)
1442 lookup_comm->type;
1443 switch (type) {
1444 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
1445 *lookup_method = NULL;
1446 break;
1447 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
1448 *lookup_method =
1449 lttng_userspace_probe_location_lookup_method_function_elf_create();
1450 if (!(*lookup_method)) {
1451 ret = -LTTNG_ERR_INVALID;
1452 goto end;
1453 }
1454 break;
f4d0bb2e
FD
1455 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
1456 *lookup_method =
1457 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1458 if (!(*lookup_method)) {
1459 ret = -LTTNG_ERR_INVALID;
1460 goto end;
1461 }
1462 break;
1ce46cfe
JG
1463 default:
1464 ret = -LTTNG_ERR_INVALID;
1465 goto end;
1466 }
1467
1468 ret = sizeof(*lookup_comm);
1469end:
1470 return ret;
1471}
1472
1473LTTNG_HIDDEN
e368fb43
JG
1474int lttng_userspace_probe_location_create_from_payload(
1475 struct lttng_payload_view *view,
1ce46cfe
JG
1476 struct lttng_userspace_probe_location **location)
1477{
1478 struct lttng_userspace_probe_location_lookup_method *lookup_method;
1ce46cfe 1479 enum lttng_userspace_probe_location_type type;
1ce46cfe
JG
1480 int consumed = 0;
1481 int ret;
3e6e0df2
JG
1482 struct lttng_userspace_probe_location_comm *probe_location_comm;
1483 struct lttng_payload_view probe_location_comm_view =
1484 lttng_payload_view_from_view(
1485 view, 0, sizeof(*probe_location_comm));
1ce46cfe 1486
e368fb43 1487 assert(view);
1ce46cfe
JG
1488 assert(location);
1489
1490 lookup_method = NULL;
1491
3e6e0df2 1492 if (!lttng_payload_view_is_valid(&probe_location_comm_view)) {
1ce46cfe
JG
1493 ret = -LTTNG_ERR_INVALID;
1494 goto end;
1495 }
1496
3e6e0df2 1497 probe_location_comm = (typeof(probe_location_comm)) probe_location_comm_view.buffer.data;
1ce46cfe
JG
1498 type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
1499 consumed += sizeof(*probe_location_comm);
1500
1501 switch (type) {
1502 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1503 {
e368fb43
JG
1504 struct lttng_payload_view location_view =
1505 lttng_payload_view_from_view(
1506 view, consumed, -1);
1ce46cfe 1507
e368fb43
JG
1508 ret = lttng_userspace_probe_location_function_create_from_payload(
1509 &location_view, location);
1ce46cfe
JG
1510 if (ret < 0) {
1511 goto end;
1512 }
1513 break;
1514 }
f4d0bb2e
FD
1515 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1516 {
e368fb43
JG
1517 struct lttng_payload_view location_view =
1518 lttng_payload_view_from_view(view, consumed, -1);
f4d0bb2e 1519
e368fb43
JG
1520 ret = lttng_userspace_probe_location_tracepoint_create_from_payload(
1521 &location_view, location);
f4d0bb2e
FD
1522 if (ret < 0) {
1523 goto end;
1524 }
1525 break;
1526 }
1ce46cfe
JG
1527 default:
1528 ret = -LTTNG_ERR_INVALID;
1529 goto end;
1530 }
1531
1532 consumed += ret;
e368fb43 1533 if (view->buffer.size <= consumed) {
1ce46cfe
JG
1534 ret = -LTTNG_ERR_INVALID;
1535 goto end;
1536 }
1537
e368fb43
JG
1538 {
1539 struct lttng_payload_view lookup_method_view =
1540 lttng_payload_view_from_view(
1541 view, consumed, -1);
1542
1543 ret = lttng_userspace_probe_location_lookup_method_create_from_payload(
1544 &lookup_method_view, &lookup_method);
1545 }
1ce46cfe
JG
1546 if (ret < 0) {
1547 ret = -LTTNG_ERR_INVALID;
1548 goto end;
1549 }
1550
1551 assert(lookup_method);
1552 (*location)->lookup_method = lookup_method;
1553 lookup_method = NULL;
1554 ret += consumed;
1555end:
1556 return ret;
1557}
1558
fe489250 1559static
2cde0510 1560int lttng_userspace_probe_location_function_set_binary_fd_handle(
fe489250
JG
1561 struct lttng_userspace_probe_location *location,
1562 struct fd_handle *binary_fd)
1ce46cfe
JG
1563{
1564 int ret = 0;
1565 struct lttng_userspace_probe_location_function *function_location;
1566
1567 assert(location);
1568 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1569
1570 function_location = container_of(location,
1571 struct lttng_userspace_probe_location_function, parent);
2cde0510 1572 fd_handle_put(function_location->binary_fd_handle);
fe489250 1573 fd_handle_get(binary_fd);
2cde0510 1574 function_location->binary_fd_handle = binary_fd;
1ce46cfe
JG
1575 return ret;
1576}
1577
fe489250 1578static
2cde0510 1579int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
fe489250
JG
1580 struct lttng_userspace_probe_location *location,
1581 struct fd_handle *binary_fd)
f4d0bb2e
FD
1582{
1583 int ret = 0;
1584 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
1585
1586 assert(location);
1587 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1588
1589 tracepoint_location = container_of(location,
1590 struct lttng_userspace_probe_location_tracepoint, parent);
2cde0510 1591 fd_handle_put(tracepoint_location->binary_fd_handle);
fe489250 1592 fd_handle_get(binary_fd);
2cde0510 1593 tracepoint_location->binary_fd_handle = binary_fd;
f4d0bb2e
FD
1594 return ret;
1595}
1596
1ce46cfe
JG
1597static
1598int lttng_userspace_probe_location_function_flatten(
1599 const struct lttng_userspace_probe_location *location,
1600 struct lttng_dynamic_buffer *buffer)
1601{
1602 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method;
1603 struct lttng_userspace_probe_location_function *probe_function;
1604 struct lttng_userspace_probe_location_function flat_probe;
1605 size_t function_name_len, binary_path_len;
1606 size_t padding_needed = 0;
1607 char *flat_probe_start;
1608 int storage_needed = 0;
1609 int ret;
1610
1611 assert(location);
1612
1613 if (location->lookup_method && location->lookup_method->type !=
1614 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF) {
1615 ret = -LTTNG_ERR_INVALID;
1616 goto end;
1617 }
1618
1619 probe_function = container_of(location,
1620 struct lttng_userspace_probe_location_function,
1621 parent);
1622 assert(probe_function->function_name);
1623 assert(probe_function->binary_path);
1624
1625 storage_needed +=
1626 sizeof(struct lttng_userspace_probe_location_function);
1627 function_name_len = strlen(probe_function->function_name) + 1;
1628 binary_path_len = strlen(probe_function->binary_path) + 1;
1629 storage_needed += function_name_len + binary_path_len;
1630
1631 /*
1632 * The lookup method is aligned to 64-bit within the buffer.
1633 * This is needed even if there is no lookup method since
1634 * the next structure in the buffer probably needs to be
1635 * aligned too (depending on the arch).
1636 */
1637 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1638 storage_needed += padding_needed;
1639
1640 if (location->lookup_method) {
1641 /* NOTE: elf look-up method is assumed here. */
1642 storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1643 }
1644
1645 if (!buffer) {
1646 ret = storage_needed;
1647 goto end;
1648 }
1649
1650 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1651 ret = lttng_dynamic_buffer_set_capacity(buffer,
1652 buffer->size + storage_needed);
1653 if (ret) {
1654 goto end;
1655 }
1656 }
1657
1658 memset(&flat_probe, 0, sizeof(flat_probe));
1659
1660 flat_probe_start = buffer->data + buffer->size;
1661 flat_probe.parent.type = location->type;
1662 /*
1663 * The lookup method, if present, is the last element in the flat
1664 * representation of the probe.
1665 */
1666 if (location->lookup_method) {
1667 flat_probe.parent.lookup_method =
1668 (struct lttng_userspace_probe_location_lookup_method *)
1669 (flat_probe_start + sizeof(flat_probe) +
1670 function_name_len + binary_path_len + padding_needed);
1671 } else {
1672 flat_probe.parent.lookup_method = NULL;
1673 }
1674
1675 flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
1676 flat_probe.binary_path = flat_probe.function_name + function_name_len;
2cde0510 1677 flat_probe.binary_fd_handle = NULL;
1ce46cfe
JG
1678 ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
1679 sizeof(flat_probe));
1680 if (ret) {
1681 goto end;
1682 }
1683
1684 ret = lttng_dynamic_buffer_append(buffer,
1685 probe_function->function_name, function_name_len);
1686 if (ret) {
1687 goto end;
1688 }
1689 ret = lttng_dynamic_buffer_append(buffer,
1690 probe_function->binary_path, binary_path_len);
1691 if (ret) {
1692 goto end;
1693 }
1694
1695 /* Insert padding before the lookup method. */
1696 ret = lttng_dynamic_buffer_set_size(buffer,
1697 buffer->size + padding_needed);
1698 if (ret) {
1699 goto end;
1700 }
1701
1702 if (!location->lookup_method) {
1703 /* Not an error, the default method is used. */
1704 ret = storage_needed;
1705 goto end;
1706 }
1707
1708 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1709 flat_lookup_method.parent.type =
1710 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
1711 ret = lttng_dynamic_buffer_append(buffer,
1712 &flat_lookup_method, sizeof(flat_lookup_method));
1713 if (ret) {
1714 goto end;
1715 }
1716 ret = storage_needed;
1717end:
1718 return ret;
1719}
1720
f4d0bb2e
FD
1721static
1722int lttng_userspace_probe_location_tracepoint_flatten(
1723 const struct lttng_userspace_probe_location *location,
1724 struct lttng_dynamic_buffer *buffer)
1725{
1726 struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method;
1727 struct lttng_userspace_probe_location_tracepoint *probe_tracepoint;
1728 struct lttng_userspace_probe_location_tracepoint flat_probe;
1729 size_t probe_name_len, provider_name_len, binary_path_len;
1730 size_t padding_needed = 0;
1731 int storage_needed = 0;
1732 char *flat_probe_start;
1733 int ret = 0;
1734
1735 assert(location);
1736
1737 /* Only SDT tracepoints are supported at the moment */
1738 if (location->lookup_method && location->lookup_method->type !=
1739 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT) {
1740 ret = -LTTNG_ERR_INVALID;
1741 goto end;
1742 }
1743 probe_tracepoint = container_of(location,
1744 struct lttng_userspace_probe_location_tracepoint,
1745 parent);
1746 assert(probe_tracepoint->probe_name);
1747 assert(probe_tracepoint->provider_name);
1748 assert(probe_tracepoint->binary_path);
1749
1750 /* Compute the storage space needed to flatten the probe location */
1751 storage_needed += sizeof(struct lttng_userspace_probe_location_tracepoint);
1752
1753 probe_name_len = strlen(probe_tracepoint->probe_name) + 1;
1754 provider_name_len = strlen(probe_tracepoint->provider_name) + 1;
1755 binary_path_len = strlen(probe_tracepoint->binary_path) + 1;
1756
1757 storage_needed += probe_name_len + provider_name_len + binary_path_len;
1758
1759 /*
1760 * The lookup method is aligned to 64-bit within the buffer.
1761 * This is needed even if there is no lookup method since
1762 * the next structure in the buffer probably needs to be
1763 * aligned too (depending on the arch).
1764 */
1765 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1766 storage_needed += padding_needed;
1767
1768 if (location->lookup_method) {
1769 /* NOTE: elf look-up method is assumed here. */
1770 storage_needed +=
1771 sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1772 }
1773
1774 /*
1775 * If the caller set buffer to NULL, return the size of the needed buffer.
1776 */
1777 if (!buffer) {
1778 ret = storage_needed;
1779 goto end;
1780 }
1781
1782 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1783 ret = lttng_dynamic_buffer_set_capacity(buffer,
1784 buffer->size + storage_needed);
1785 if (ret) {
1786 goto end;
1787 }
1788 }
1789
1790 memset(&flat_probe, 0, sizeof(flat_probe));
1791
1792 flat_probe_start = buffer->data + buffer->size;
1793 flat_probe.parent.type = location->type;
1794
1795 /*
1796 * The lookup method, if present, is the last element in the flat
1797 * representation of the probe.
1798 */
1799 if (location->lookup_method) {
1800 flat_probe.parent.lookup_method =
1801 (struct lttng_userspace_probe_location_lookup_method *)
1802 (flat_probe_start + sizeof(flat_probe) +
1803 probe_name_len + provider_name_len +
1804 binary_path_len + padding_needed);
1805 } else {
1806 flat_probe.parent.lookup_method = NULL;
1807 }
1808
1809 flat_probe.probe_name = flat_probe_start + sizeof(flat_probe);
1810 flat_probe.provider_name = flat_probe.probe_name + probe_name_len;
1811 flat_probe.binary_path = flat_probe.provider_name + provider_name_len;
2cde0510 1812 flat_probe.binary_fd_handle = NULL;
f4d0bb2e
FD
1813 ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe));
1814 if (ret) {
1815 goto end;
1816 }
1817
1818 /* Append all the fields to the buffer */
1819 ret = lttng_dynamic_buffer_append(buffer,
1820 probe_tracepoint->probe_name, probe_name_len);
1821 if (ret) {
1822 goto end;
1823 }
1824 ret = lttng_dynamic_buffer_append(buffer,
1825 probe_tracepoint->provider_name, provider_name_len);
1826 if (ret) {
1827 goto end;
1828 }
1829 ret = lttng_dynamic_buffer_append(buffer,
1830 probe_tracepoint->binary_path, binary_path_len);
1831 if (ret) {
1832 goto end;
1833 }
1834
1835 /* Insert padding before the lookup method. */
1836 ret = lttng_dynamic_buffer_set_size(buffer, buffer->size + padding_needed);
1837 if (ret) {
1838 goto end;
1839 }
1840
1841 if (!location->lookup_method) {
1842 /* Not an error, the default method is used. */
1843 ret = storage_needed;
1844 goto end;
1845 }
1846
1847 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1848
1849 flat_lookup_method.parent.type =
1850 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
1851 ret = lttng_dynamic_buffer_append(buffer,
1852 &flat_lookup_method, sizeof(flat_lookup_method));
1853 if (ret) {
1854 goto end;
1855 }
1856 ret = storage_needed;
1857end:
1858 return ret;
1859}
1860
1ce46cfe
JG
1861LTTNG_HIDDEN
1862int lttng_userspace_probe_location_flatten(
1863 const struct lttng_userspace_probe_location *location,
1864 struct lttng_dynamic_buffer *buffer)
1865{
1866 int ret;
1867 if (!location) {
1868 ret = -LTTNG_ERR_INVALID;
1869 goto end;
1870 }
1871
1872 /* Only types currently supported. */
1873 switch (location->type) {
1874 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1875 ret = lttng_userspace_probe_location_function_flatten(location, buffer);
1876 break;
f4d0bb2e
FD
1877 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1878 ret = lttng_userspace_probe_location_tracepoint_flatten(location, buffer);
1879 break;
1ce46cfe
JG
1880 default:
1881 ret = -LTTNG_ERR_INVALID;
1882 goto end;
1883 }
1884
1885end:
1886 return ret;
1887}
394357fe
FD
1888
1889LTTNG_HIDDEN
1890struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
1891 const struct lttng_userspace_probe_location *location)
1892{
1893 struct lttng_userspace_probe_location *new_location = NULL;
1894 enum lttng_userspace_probe_location_type type;
1895
1896 if (!location) {
1897 goto err;
1898 }
1899
1900 type = lttng_userspace_probe_location_get_type(location);
1901 switch (type) {
1902 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1903 new_location =
1904 lttng_userspace_probe_location_function_copy(location);
1905 if (!new_location) {
1906 goto err;
1907 }
1908 break;
f4d0bb2e
FD
1909 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1910 new_location =
1911 lttng_userspace_probe_location_tracepoint_copy(location);
1912 if (!new_location) {
1913 goto err;
1914 }
1915 break;
394357fe
FD
1916 default:
1917 new_location = NULL;
1918 goto err;
1919 }
1920err:
1921 return new_location;
1922}
dfcfa983
JR
1923
1924LTTNG_HIDDEN
1925bool lttng_userspace_probe_location_lookup_method_is_equal(
1926 const struct lttng_userspace_probe_location_lookup_method *a,
1927 const struct lttng_userspace_probe_location_lookup_method *b)
1928{
1929 bool is_equal = false;
1930
1931 if (!a || !b) {
1932 goto end;
1933 }
1934
1935 if (a == b) {
1936 is_equal = true;
1937 goto end;
1938 }
1939
1940 if (a->type != b->type) {
1941 goto end;
1942 }
1943
1944 is_equal = true;
1945end:
1946 return is_equal;
1947}
1948
1949LTTNG_HIDDEN
1950bool lttng_userspace_probe_location_is_equal(
1951 const struct lttng_userspace_probe_location *a,
1952 const struct lttng_userspace_probe_location *b)
1953{
1954 bool is_equal = false;
1955
1956 if (!a || !b) {
1957 goto end;
1958 }
1959
1960 if (a == b) {
1961 is_equal = true;
1962 goto end;
1963 }
1964
1965 if (!lttng_userspace_probe_location_lookup_method_is_equal(
1966 a->lookup_method, b->lookup_method)) {
1967 goto end;
1968 }
1969
1970 if (a->type != b->type) {
1971 goto end;
1972 }
1973
1974 is_equal = a->equal ? a->equal(a, b) : true;
1975end:
1976 return is_equal;
1977}
959e3c66
JR
1978
1979LTTNG_HIDDEN
1980unsigned long lttng_userspace_probe_location_hash(
1981 const struct lttng_userspace_probe_location *location)
1982{
1983 return location->hash(location);
1984}
6a751b95
JR
1985
1986LTTNG_HIDDEN
1987enum lttng_error_code lttng_userspace_probe_location_mi_serialize(
1988 const struct lttng_userspace_probe_location *location,
1989 struct mi_writer *writer)
1990{
1991 typedef enum lttng_error_code (*mi_fp)(
1992 const struct lttng_userspace_probe_location *,
1993 struct mi_writer *);
1994
1995 int ret;
1996 enum lttng_error_code ret_code;
1997 mi_fp mi_function = NULL;
1998
1999 assert(location);
2000 assert(writer);
2001
2002 switch (lttng_userspace_probe_location_get_type(location)) {
2003 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
2004 mi_function = lttng_userspace_probe_location_function_mi_serialize;
2005 break;
2006 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
2007 mi_function = lttng_userspace_probe_location_tracepoint_mi_serialize;
2008 break;
2009 default:
2010 abort();
2011 break;
2012 }
2013
2014 /* Open userspace probe location element. */
2015 ret = mi_lttng_writer_open_element(
2016 writer, mi_lttng_element_userspace_probe_location);
2017 if (ret) {
2018 goto mi_error;
2019 }
2020
2021 /* Underlying user space probe location. */
2022 ret_code = mi_function(location, writer);
2023 if (ret_code != LTTNG_OK) {
2024 goto end;
2025 }
2026
2027 /* Close userspace probe location element. */
2028 ret = mi_lttng_writer_close_element(writer);
2029 if (ret) {
2030 goto mi_error;
2031 }
2032
2033 ret_code = LTTNG_OK;
2034 goto end;
2035
2036mi_error:
2037 ret_code = LTTNG_ERR_MI_IO_FAIL;
2038end:
2039 return ret_code;
2040}
2041
2042enum lttng_error_code lttng_userspace_probe_location_lookup_method_mi_serialize(
2043 const struct lttng_userspace_probe_location_lookup_method
2044 *method,
2045 struct mi_writer *writer)
2046{
2047 int ret;
2048 enum lttng_error_code ret_code;
2049 const char *type_element_str;
2050
2051 assert(method);
2052 assert(writer);
2053
2054 switch (lttng_userspace_probe_location_lookup_method_get_type(method)) {
2055 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
2056 type_element_str =
2057 mi_lttng_element_userspace_probe_location_lookup_method_function_default;
2058 break;
2059 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
2060 type_element_str =
2061 mi_lttng_element_userspace_probe_location_lookup_method_function_elf;
2062 break;
2063 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
2064 type_element_str =
2065 mi_lttng_element_userspace_probe_location_lookup_method_tracepoint_sdt;
2066 break;
2067 default:
2068 abort();
2069 break;
2070 }
2071
2072 /* Open userspace probe location lookup method element. */
2073 ret = mi_lttng_writer_open_element(writer,
2074 mi_lttng_element_userspace_probe_location_lookup_method);
2075 if (ret) {
2076 goto mi_error;
2077 }
2078
2079 /* User space probe location lookup method empty element. */
2080 ret = mi_lttng_writer_open_element(writer, type_element_str);
2081 if (ret) {
2082 goto mi_error;
2083 }
2084
2085 /* Close userspace probe location lookup method element. */
2086 ret = mi_lttng_close_multi_element(writer, 2);
2087 if (ret) {
2088 goto mi_error;
2089 }
2090
2091 ret_code = LTTNG_OK;
2092 goto end;
2093
2094mi_error:
2095 ret_code = LTTNG_ERR_MI_IO_FAIL;
2096end:
2097 return ret_code;
2098}
2099
2100static enum lttng_error_code lttng_userspace_probe_location_tracepoint_mi_serialize(
2101 const struct lttng_userspace_probe_location *location,
2102 struct mi_writer *writer)
2103{
2104 int ret;
2105 enum lttng_error_code ret_code;
2106 const char *probe_name = NULL;
2107 const char *provider_name = NULL;
2108 const char *binary_path = NULL;
2109 const struct lttng_userspace_probe_location_lookup_method
2110 *lookup_method = NULL;
2111
2112 assert(location);
2113 assert(writer);
2114
2115 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(
2116 location);
2117 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(
2118 location);
2119 binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(
2120 location);
2121 lookup_method = lttng_userspace_probe_location_tracepoint_get_lookup_method(
2122 location);
2123
2124 /* Open userspace probe location tracepoint element. */
2125 ret = mi_lttng_writer_open_element(writer,
2126 mi_lttng_element_userspace_probe_location_tracepoint);
2127 if (ret) {
2128 goto mi_error;
2129 }
2130
2131 /* Probe name. */
2132 ret = mi_lttng_writer_write_element_string(writer,
2133 mi_lttng_element_userspace_probe_location_tracepoint_probe_name,
2134 probe_name);
2135 if (ret) {
2136 goto mi_error;
2137 }
2138
2139 /* Provider name. */
2140 ret = mi_lttng_writer_write_element_string(writer,
2141 mi_lttng_element_userspace_probe_location_tracepoint_provider_name,
2142 provider_name);
2143 if (ret) {
2144 goto mi_error;
2145 }
2146
2147 /* Binary path. */
2148 ret = mi_lttng_writer_write_element_string(writer,
2149 mi_lttng_element_userspace_probe_location_binary_path,
2150 binary_path);
2151 if (ret) {
2152 goto mi_error;
2153 }
2154
2155 /* The lookup method. */
2156 ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize(
2157 lookup_method, writer);
2158 if (ret_code != LTTNG_OK) {
2159 goto end;
2160 }
2161
2162 /* Close userspace probe location tracepoint. */
2163 ret = mi_lttng_writer_close_element(writer);
2164 if (ret) {
2165 goto mi_error;
2166 }
2167
2168 ret_code = LTTNG_OK;
2169 goto end;
2170
2171mi_error:
2172 ret_code = LTTNG_ERR_MI_IO_FAIL;
2173end:
2174 return ret_code;
2175}
2176
2177static enum lttng_error_code lttng_userspace_probe_location_function_mi_serialize(
2178 const struct lttng_userspace_probe_location *location,
2179 struct mi_writer *writer)
2180{
2181 int ret;
2182 enum lttng_error_code ret_code;
2183 const char *function_name = NULL;
2184 const char *binary_path = NULL;
2185 const char *instrumentation_type_str = NULL;
2186 enum lttng_userspace_probe_location_function_instrumentation_type
2187 instrumentation_type;
2188 const struct lttng_userspace_probe_location_lookup_method
2189 *lookup_method = NULL;
2190
2191 assert(location);
2192 assert(writer);
2193
2194 function_name = lttng_userspace_probe_location_function_get_function_name(
2195 location);
2196 binary_path = lttng_userspace_probe_location_function_get_binary_path(
2197 location);
2198 instrumentation_type =
2199 lttng_userspace_probe_location_function_get_instrumentation_type(
2200 location);
2201 lookup_method = lttng_userspace_probe_location_function_get_lookup_method(
2202 location);
2203
2204 switch (instrumentation_type) {
2205 case LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY:
2206 instrumentation_type_str =
2207 mi_lttng_userspace_probe_location_function_instrumentation_type_entry;
2208 break;
2209 default:
2210 abort();
2211 break;
2212 }
2213
2214 /* Open userspace probe location function element. */
2215 ret = mi_lttng_writer_open_element(writer,
2216 mi_lttng_element_userspace_probe_location_function);
2217 if (ret) {
2218 goto mi_error;
2219 }
2220
2221 /* Function name. */
2222 ret = mi_lttng_writer_write_element_string(writer,
2223 mi_lttng_element_userspace_probe_location_function_name,
2224 function_name);
2225 if (ret) {
2226 goto mi_error;
2227 }
2228
2229 /* Binary path. */
2230 ret = mi_lttng_writer_write_element_string(writer,
2231 mi_lttng_element_userspace_probe_location_binary_path,
2232 binary_path);
2233 if (ret) {
2234 goto mi_error;
2235 }
2236
2237 /* Instrumentation type. */
2238 ret = mi_lttng_writer_write_element_string(writer,
2239 mi_lttng_element_userspace_probe_location_function_instrumentation_type,
2240 instrumentation_type_str);
2241 if (ret) {
2242 goto mi_error;
2243 }
2244
2245 /* The lookup method. */
2246 ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize(
2247 lookup_method, writer);
2248 if (ret_code != LTTNG_OK) {
2249 goto end;
2250 }
2251
2252 /* Close userspace probe location function element. */
2253 ret = mi_lttng_writer_close_element(writer);
2254 if (ret) {
2255 goto mi_error;
2256 }
2257
2258 ret_code = LTTNG_OK;
2259 goto end;
2260
2261mi_error:
2262 ret_code = LTTNG_ERR_MI_IO_FAIL;
2263end:
2264 return ret_code;
2265}
This page took 0.130828 seconds and 4 git commands to generate.