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