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