Fix: userspace-probe: unreported error on string copy error
[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) {
c21e883d
JG
1384 PERROR("Failed to allocate probe name");
1385 ret = -LTTNG_ERR_INVALID;
f4d0bb2e
FD
1386 goto end;
1387 }
1388 provider_name = lttng_strndup(provider_name_src, LTTNG_SYMBOL_NAME_LEN);
1389 if (!provider_name) {
c21e883d
JG
1390 PERROR("Failed to allocate provider name");
1391 ret = -LTTNG_ERR_INVALID;
f4d0bb2e
FD
1392 goto end;
1393 }
1394
b45a2969 1395 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
f4d0bb2e 1396 if (!binary_path) {
c21e883d
JG
1397 PERROR("Failed to allocate binary path");
1398 ret = -LTTNG_ERR_INVALID;
f4d0bb2e
FD
1399 goto end;
1400 }
1401
1402 *location = lttng_userspace_probe_location_tracepoint_create_no_check(
1403 binary_path, provider_name, probe_name, NULL, false);
1404 if (!(*location)) {
1405 ret = -LTTNG_ERR_INVALID;
1406 goto end;
1407 }
1408
2cde0510
JG
1409 ret = lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
1410 *location, binary_fd_handle);
e368fb43 1411 if (ret) {
e368fb43
JG
1412 ret = -LTTNG_ERR_INVALID;
1413 goto end;
1414 }
1415
f4d0bb2e
FD
1416 ret = (int) expected_size;
1417end:
2cde0510 1418 fd_handle_put(binary_fd_handle);
f4d0bb2e
FD
1419 free(probe_name);
1420 free(provider_name);
1421 free(binary_path);
1422 return ret;
1423}
1424
1ce46cfe 1425static
e368fb43
JG
1426int lttng_userspace_probe_location_lookup_method_create_from_payload(
1427 struct lttng_payload_view *view,
1ce46cfe
JG
1428 struct lttng_userspace_probe_location_lookup_method **lookup_method)
1429{
1430 int ret;
1431 struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
1432 enum lttng_userspace_probe_location_lookup_method_type type;
1433
a0377dfe
FD
1434 LTTNG_ASSERT(view);
1435 LTTNG_ASSERT(lookup_method);
1ce46cfe 1436
e368fb43 1437 if (view->buffer.size < sizeof(*lookup_comm)) {
1ce46cfe
JG
1438 ret = -LTTNG_ERR_INVALID;
1439 goto end;
1440 }
1441
e368fb43 1442 lookup_comm = (typeof(lookup_comm)) view->buffer.data;
1ce46cfe
JG
1443 type = (enum lttng_userspace_probe_location_lookup_method_type)
1444 lookup_comm->type;
1445 switch (type) {
1446 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
1447 *lookup_method = NULL;
1448 break;
1449 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
1450 *lookup_method =
1451 lttng_userspace_probe_location_lookup_method_function_elf_create();
1452 if (!(*lookup_method)) {
1453 ret = -LTTNG_ERR_INVALID;
1454 goto end;
1455 }
1456 break;
f4d0bb2e
FD
1457 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
1458 *lookup_method =
1459 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1460 if (!(*lookup_method)) {
1461 ret = -LTTNG_ERR_INVALID;
1462 goto end;
1463 }
1464 break;
1ce46cfe
JG
1465 default:
1466 ret = -LTTNG_ERR_INVALID;
1467 goto end;
1468 }
1469
1470 ret = sizeof(*lookup_comm);
1471end:
1472 return ret;
1473}
1474
1475LTTNG_HIDDEN
e368fb43
JG
1476int lttng_userspace_probe_location_create_from_payload(
1477 struct lttng_payload_view *view,
1ce46cfe
JG
1478 struct lttng_userspace_probe_location **location)
1479{
1480 struct lttng_userspace_probe_location_lookup_method *lookup_method;
1ce46cfe 1481 enum lttng_userspace_probe_location_type type;
1ce46cfe
JG
1482 int consumed = 0;
1483 int ret;
3e6e0df2
JG
1484 struct lttng_userspace_probe_location_comm *probe_location_comm;
1485 struct lttng_payload_view probe_location_comm_view =
1486 lttng_payload_view_from_view(
1487 view, 0, sizeof(*probe_location_comm));
1ce46cfe 1488
a0377dfe
FD
1489 LTTNG_ASSERT(view);
1490 LTTNG_ASSERT(location);
1ce46cfe
JG
1491
1492 lookup_method = NULL;
1493
3e6e0df2 1494 if (!lttng_payload_view_is_valid(&probe_location_comm_view)) {
1ce46cfe
JG
1495 ret = -LTTNG_ERR_INVALID;
1496 goto end;
1497 }
1498
3e6e0df2 1499 probe_location_comm = (typeof(probe_location_comm)) probe_location_comm_view.buffer.data;
1ce46cfe
JG
1500 type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
1501 consumed += sizeof(*probe_location_comm);
1502
1503 switch (type) {
1504 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1505 {
e368fb43
JG
1506 struct lttng_payload_view location_view =
1507 lttng_payload_view_from_view(
1508 view, consumed, -1);
1ce46cfe 1509
e368fb43
JG
1510 ret = lttng_userspace_probe_location_function_create_from_payload(
1511 &location_view, location);
1ce46cfe
JG
1512 if (ret < 0) {
1513 goto end;
1514 }
1515 break;
1516 }
f4d0bb2e
FD
1517 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1518 {
e368fb43
JG
1519 struct lttng_payload_view location_view =
1520 lttng_payload_view_from_view(view, consumed, -1);
f4d0bb2e 1521
e368fb43
JG
1522 ret = lttng_userspace_probe_location_tracepoint_create_from_payload(
1523 &location_view, location);
f4d0bb2e
FD
1524 if (ret < 0) {
1525 goto end;
1526 }
1527 break;
1528 }
1ce46cfe
JG
1529 default:
1530 ret = -LTTNG_ERR_INVALID;
1531 goto end;
1532 }
1533
1534 consumed += ret;
e368fb43 1535 if (view->buffer.size <= consumed) {
1ce46cfe
JG
1536 ret = -LTTNG_ERR_INVALID;
1537 goto end;
1538 }
1539
e368fb43
JG
1540 {
1541 struct lttng_payload_view lookup_method_view =
1542 lttng_payload_view_from_view(
1543 view, consumed, -1);
1544
1545 ret = lttng_userspace_probe_location_lookup_method_create_from_payload(
1546 &lookup_method_view, &lookup_method);
1547 }
1ce46cfe
JG
1548 if (ret < 0) {
1549 ret = -LTTNG_ERR_INVALID;
1550 goto end;
1551 }
1552
a0377dfe 1553 LTTNG_ASSERT(lookup_method);
1ce46cfe
JG
1554 (*location)->lookup_method = lookup_method;
1555 lookup_method = NULL;
1556 ret += consumed;
1557end:
1558 return ret;
1559}
1560
fe489250 1561static
2cde0510 1562int lttng_userspace_probe_location_function_set_binary_fd_handle(
fe489250
JG
1563 struct lttng_userspace_probe_location *location,
1564 struct fd_handle *binary_fd)
1ce46cfe
JG
1565{
1566 int ret = 0;
1567 struct lttng_userspace_probe_location_function *function_location;
1568
a0377dfe
FD
1569 LTTNG_ASSERT(location);
1570 LTTNG_ASSERT(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1ce46cfe
JG
1571
1572 function_location = container_of(location,
1573 struct lttng_userspace_probe_location_function, parent);
2cde0510 1574 fd_handle_put(function_location->binary_fd_handle);
fe489250 1575 fd_handle_get(binary_fd);
2cde0510 1576 function_location->binary_fd_handle = binary_fd;
1ce46cfe
JG
1577 return ret;
1578}
1579
fe489250 1580static
2cde0510 1581int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
fe489250
JG
1582 struct lttng_userspace_probe_location *location,
1583 struct fd_handle *binary_fd)
f4d0bb2e
FD
1584{
1585 int ret = 0;
1586 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
1587
a0377dfe
FD
1588 LTTNG_ASSERT(location);
1589 LTTNG_ASSERT(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
f4d0bb2e
FD
1590
1591 tracepoint_location = container_of(location,
1592 struct lttng_userspace_probe_location_tracepoint, parent);
2cde0510 1593 fd_handle_put(tracepoint_location->binary_fd_handle);
fe489250 1594 fd_handle_get(binary_fd);
2cde0510 1595 tracepoint_location->binary_fd_handle = binary_fd;
f4d0bb2e
FD
1596 return ret;
1597}
1598
1ce46cfe
JG
1599static
1600int lttng_userspace_probe_location_function_flatten(
1601 const struct lttng_userspace_probe_location *location,
1602 struct lttng_dynamic_buffer *buffer)
1603{
1604 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method;
1605 struct lttng_userspace_probe_location_function *probe_function;
1606 struct lttng_userspace_probe_location_function flat_probe;
1607 size_t function_name_len, binary_path_len;
1608 size_t padding_needed = 0;
1609 char *flat_probe_start;
1610 int storage_needed = 0;
1611 int ret;
1612
a0377dfe 1613 LTTNG_ASSERT(location);
1ce46cfe
JG
1614
1615 if (location->lookup_method && location->lookup_method->type !=
1616 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF) {
1617 ret = -LTTNG_ERR_INVALID;
1618 goto end;
1619 }
1620
1621 probe_function = container_of(location,
1622 struct lttng_userspace_probe_location_function,
1623 parent);
a0377dfe
FD
1624 LTTNG_ASSERT(probe_function->function_name);
1625 LTTNG_ASSERT(probe_function->binary_path);
1ce46cfe
JG
1626
1627 storage_needed +=
1628 sizeof(struct lttng_userspace_probe_location_function);
1629 function_name_len = strlen(probe_function->function_name) + 1;
1630 binary_path_len = strlen(probe_function->binary_path) + 1;
1631 storage_needed += function_name_len + binary_path_len;
1632
1633 /*
1634 * The lookup method is aligned to 64-bit within the buffer.
1635 * This is needed even if there is no lookup method since
1636 * the next structure in the buffer probably needs to be
1637 * aligned too (depending on the arch).
1638 */
1639 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1640 storage_needed += padding_needed;
1641
1642 if (location->lookup_method) {
1643 /* NOTE: elf look-up method is assumed here. */
1644 storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1645 }
1646
1647 if (!buffer) {
1648 ret = storage_needed;
1649 goto end;
1650 }
1651
1652 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1653 ret = lttng_dynamic_buffer_set_capacity(buffer,
1654 buffer->size + storage_needed);
1655 if (ret) {
1656 goto end;
1657 }
1658 }
1659
1660 memset(&flat_probe, 0, sizeof(flat_probe));
1661
1662 flat_probe_start = buffer->data + buffer->size;
1663 flat_probe.parent.type = location->type;
1664 /*
1665 * The lookup method, if present, is the last element in the flat
1666 * representation of the probe.
1667 */
1668 if (location->lookup_method) {
1669 flat_probe.parent.lookup_method =
1670 (struct lttng_userspace_probe_location_lookup_method *)
1671 (flat_probe_start + sizeof(flat_probe) +
1672 function_name_len + binary_path_len + padding_needed);
1673 } else {
1674 flat_probe.parent.lookup_method = NULL;
1675 }
1676
1677 flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
1678 flat_probe.binary_path = flat_probe.function_name + function_name_len;
2cde0510 1679 flat_probe.binary_fd_handle = NULL;
1ce46cfe
JG
1680 ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
1681 sizeof(flat_probe));
1682 if (ret) {
1683 goto end;
1684 }
1685
1686 ret = lttng_dynamic_buffer_append(buffer,
1687 probe_function->function_name, function_name_len);
1688 if (ret) {
1689 goto end;
1690 }
1691 ret = lttng_dynamic_buffer_append(buffer,
1692 probe_function->binary_path, binary_path_len);
1693 if (ret) {
1694 goto end;
1695 }
1696
1697 /* Insert padding before the lookup method. */
1698 ret = lttng_dynamic_buffer_set_size(buffer,
1699 buffer->size + padding_needed);
1700 if (ret) {
1701 goto end;
1702 }
1703
1704 if (!location->lookup_method) {
1705 /* Not an error, the default method is used. */
1706 ret = storage_needed;
1707 goto end;
1708 }
1709
1710 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1711 flat_lookup_method.parent.type =
1712 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
1713 ret = lttng_dynamic_buffer_append(buffer,
1714 &flat_lookup_method, sizeof(flat_lookup_method));
1715 if (ret) {
1716 goto end;
1717 }
1718 ret = storage_needed;
1719end:
1720 return ret;
1721}
1722
f4d0bb2e
FD
1723static
1724int lttng_userspace_probe_location_tracepoint_flatten(
1725 const struct lttng_userspace_probe_location *location,
1726 struct lttng_dynamic_buffer *buffer)
1727{
1728 struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method;
1729 struct lttng_userspace_probe_location_tracepoint *probe_tracepoint;
1730 struct lttng_userspace_probe_location_tracepoint flat_probe;
1731 size_t probe_name_len, provider_name_len, binary_path_len;
1732 size_t padding_needed = 0;
1733 int storage_needed = 0;
1734 char *flat_probe_start;
1735 int ret = 0;
1736
a0377dfe 1737 LTTNG_ASSERT(location);
f4d0bb2e
FD
1738
1739 /* Only SDT tracepoints are supported at the moment */
1740 if (location->lookup_method && location->lookup_method->type !=
1741 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT) {
1742 ret = -LTTNG_ERR_INVALID;
1743 goto end;
1744 }
1745 probe_tracepoint = container_of(location,
1746 struct lttng_userspace_probe_location_tracepoint,
1747 parent);
a0377dfe
FD
1748 LTTNG_ASSERT(probe_tracepoint->probe_name);
1749 LTTNG_ASSERT(probe_tracepoint->provider_name);
1750 LTTNG_ASSERT(probe_tracepoint->binary_path);
f4d0bb2e
FD
1751
1752 /* Compute the storage space needed to flatten the probe location */
1753 storage_needed += sizeof(struct lttng_userspace_probe_location_tracepoint);
1754
1755 probe_name_len = strlen(probe_tracepoint->probe_name) + 1;
1756 provider_name_len = strlen(probe_tracepoint->provider_name) + 1;
1757 binary_path_len = strlen(probe_tracepoint->binary_path) + 1;
1758
1759 storage_needed += probe_name_len + provider_name_len + binary_path_len;
1760
1761 /*
1762 * The lookup method is aligned to 64-bit within the buffer.
1763 * This is needed even if there is no lookup method since
1764 * the next structure in the buffer probably needs to be
1765 * aligned too (depending on the arch).
1766 */
1767 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
1768 storage_needed += padding_needed;
1769
1770 if (location->lookup_method) {
1771 /* NOTE: elf look-up method is assumed here. */
1772 storage_needed +=
1773 sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1774 }
1775
1776 /*
1777 * If the caller set buffer to NULL, return the size of the needed buffer.
1778 */
1779 if (!buffer) {
1780 ret = storage_needed;
1781 goto end;
1782 }
1783
1784 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1785 ret = lttng_dynamic_buffer_set_capacity(buffer,
1786 buffer->size + storage_needed);
1787 if (ret) {
1788 goto end;
1789 }
1790 }
1791
1792 memset(&flat_probe, 0, sizeof(flat_probe));
1793
1794 flat_probe_start = buffer->data + buffer->size;
1795 flat_probe.parent.type = location->type;
1796
1797 /*
1798 * The lookup method, if present, is the last element in the flat
1799 * representation of the probe.
1800 */
1801 if (location->lookup_method) {
1802 flat_probe.parent.lookup_method =
1803 (struct lttng_userspace_probe_location_lookup_method *)
1804 (flat_probe_start + sizeof(flat_probe) +
1805 probe_name_len + provider_name_len +
1806 binary_path_len + padding_needed);
1807 } else {
1808 flat_probe.parent.lookup_method = NULL;
1809 }
1810
1811 flat_probe.probe_name = flat_probe_start + sizeof(flat_probe);
1812 flat_probe.provider_name = flat_probe.probe_name + probe_name_len;
1813 flat_probe.binary_path = flat_probe.provider_name + provider_name_len;
2cde0510 1814 flat_probe.binary_fd_handle = NULL;
f4d0bb2e
FD
1815 ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe));
1816 if (ret) {
1817 goto end;
1818 }
1819
1820 /* Append all the fields to the buffer */
1821 ret = lttng_dynamic_buffer_append(buffer,
1822 probe_tracepoint->probe_name, probe_name_len);
1823 if (ret) {
1824 goto end;
1825 }
1826 ret = lttng_dynamic_buffer_append(buffer,
1827 probe_tracepoint->provider_name, provider_name_len);
1828 if (ret) {
1829 goto end;
1830 }
1831 ret = lttng_dynamic_buffer_append(buffer,
1832 probe_tracepoint->binary_path, binary_path_len);
1833 if (ret) {
1834 goto end;
1835 }
1836
1837 /* Insert padding before the lookup method. */
1838 ret = lttng_dynamic_buffer_set_size(buffer, buffer->size + padding_needed);
1839 if (ret) {
1840 goto end;
1841 }
1842
1843 if (!location->lookup_method) {
1844 /* Not an error, the default method is used. */
1845 ret = storage_needed;
1846 goto end;
1847 }
1848
1849 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1850
1851 flat_lookup_method.parent.type =
1852 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
1853 ret = lttng_dynamic_buffer_append(buffer,
1854 &flat_lookup_method, sizeof(flat_lookup_method));
1855 if (ret) {
1856 goto end;
1857 }
1858 ret = storage_needed;
1859end:
1860 return ret;
1861}
1862
1ce46cfe
JG
1863LTTNG_HIDDEN
1864int lttng_userspace_probe_location_flatten(
1865 const struct lttng_userspace_probe_location *location,
1866 struct lttng_dynamic_buffer *buffer)
1867{
1868 int ret;
1869 if (!location) {
1870 ret = -LTTNG_ERR_INVALID;
1871 goto end;
1872 }
1873
1874 /* Only types currently supported. */
1875 switch (location->type) {
1876 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1877 ret = lttng_userspace_probe_location_function_flatten(location, buffer);
1878 break;
f4d0bb2e
FD
1879 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1880 ret = lttng_userspace_probe_location_tracepoint_flatten(location, buffer);
1881 break;
1ce46cfe
JG
1882 default:
1883 ret = -LTTNG_ERR_INVALID;
1884 goto end;
1885 }
1886
1887end:
1888 return ret;
1889}
394357fe
FD
1890
1891LTTNG_HIDDEN
1892struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
1893 const struct lttng_userspace_probe_location *location)
1894{
1895 struct lttng_userspace_probe_location *new_location = NULL;
1896 enum lttng_userspace_probe_location_type type;
1897
1898 if (!location) {
1899 goto err;
1900 }
1901
1902 type = lttng_userspace_probe_location_get_type(location);
1903 switch (type) {
1904 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1905 new_location =
1906 lttng_userspace_probe_location_function_copy(location);
1907 if (!new_location) {
1908 goto err;
1909 }
1910 break;
f4d0bb2e
FD
1911 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1912 new_location =
1913 lttng_userspace_probe_location_tracepoint_copy(location);
1914 if (!new_location) {
1915 goto err;
1916 }
1917 break;
394357fe
FD
1918 default:
1919 new_location = NULL;
1920 goto err;
1921 }
1922err:
1923 return new_location;
1924}
dfcfa983
JR
1925
1926LTTNG_HIDDEN
1927bool lttng_userspace_probe_location_lookup_method_is_equal(
1928 const struct lttng_userspace_probe_location_lookup_method *a,
1929 const struct lttng_userspace_probe_location_lookup_method *b)
1930{
1931 bool is_equal = false;
1932
1933 if (!a || !b) {
1934 goto end;
1935 }
1936
1937 if (a == b) {
1938 is_equal = true;
1939 goto end;
1940 }
1941
1942 if (a->type != b->type) {
1943 goto end;
1944 }
1945
1946 is_equal = true;
1947end:
1948 return is_equal;
1949}
1950
1951LTTNG_HIDDEN
1952bool lttng_userspace_probe_location_is_equal(
1953 const struct lttng_userspace_probe_location *a,
1954 const struct lttng_userspace_probe_location *b)
1955{
1956 bool is_equal = false;
1957
1958 if (!a || !b) {
1959 goto end;
1960 }
1961
1962 if (a == b) {
1963 is_equal = true;
1964 goto end;
1965 }
1966
1967 if (!lttng_userspace_probe_location_lookup_method_is_equal(
1968 a->lookup_method, b->lookup_method)) {
1969 goto end;
1970 }
1971
1972 if (a->type != b->type) {
1973 goto end;
1974 }
1975
1976 is_equal = a->equal ? a->equal(a, b) : true;
1977end:
1978 return is_equal;
1979}
959e3c66
JR
1980
1981LTTNG_HIDDEN
1982unsigned long lttng_userspace_probe_location_hash(
1983 const struct lttng_userspace_probe_location *location)
1984{
1985 return location->hash(location);
1986}
6a751b95
JR
1987
1988LTTNG_HIDDEN
1989enum lttng_error_code lttng_userspace_probe_location_mi_serialize(
1990 const struct lttng_userspace_probe_location *location,
1991 struct mi_writer *writer)
1992{
1993 typedef enum lttng_error_code (*mi_fp)(
1994 const struct lttng_userspace_probe_location *,
1995 struct mi_writer *);
1996
1997 int ret;
1998 enum lttng_error_code ret_code;
1999 mi_fp mi_function = NULL;
2000
a0377dfe
FD
2001 LTTNG_ASSERT(location);
2002 LTTNG_ASSERT(writer);
6a751b95
JR
2003
2004 switch (lttng_userspace_probe_location_get_type(location)) {
2005 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
2006 mi_function = lttng_userspace_probe_location_function_mi_serialize;
2007 break;
2008 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
2009 mi_function = lttng_userspace_probe_location_tracepoint_mi_serialize;
2010 break;
2011 default:
2012 abort();
2013 break;
2014 }
2015
2016 /* Open userspace probe location element. */
2017 ret = mi_lttng_writer_open_element(
2018 writer, mi_lttng_element_userspace_probe_location);
2019 if (ret) {
2020 goto mi_error;
2021 }
2022
2023 /* Underlying user space probe location. */
2024 ret_code = mi_function(location, writer);
2025 if (ret_code != LTTNG_OK) {
2026 goto end;
2027 }
2028
2029 /* Close userspace probe location element. */
2030 ret = mi_lttng_writer_close_element(writer);
2031 if (ret) {
2032 goto mi_error;
2033 }
2034
2035 ret_code = LTTNG_OK;
2036 goto end;
2037
2038mi_error:
2039 ret_code = LTTNG_ERR_MI_IO_FAIL;
2040end:
2041 return ret_code;
2042}
2043
2044enum lttng_error_code lttng_userspace_probe_location_lookup_method_mi_serialize(
2045 const struct lttng_userspace_probe_location_lookup_method
2046 *method,
2047 struct mi_writer *writer)
2048{
2049 int ret;
2050 enum lttng_error_code ret_code;
2051 const char *type_element_str;
2052
a0377dfe
FD
2053 LTTNG_ASSERT(method);
2054 LTTNG_ASSERT(writer);
6a751b95
JR
2055
2056 switch (lttng_userspace_probe_location_lookup_method_get_type(method)) {
2057 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
2058 type_element_str =
2059 mi_lttng_element_userspace_probe_location_lookup_method_function_default;
2060 break;
2061 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
2062 type_element_str =
2063 mi_lttng_element_userspace_probe_location_lookup_method_function_elf;
2064 break;
2065 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
2066 type_element_str =
2067 mi_lttng_element_userspace_probe_location_lookup_method_tracepoint_sdt;
2068 break;
2069 default:
2070 abort();
2071 break;
2072 }
2073
2074 /* Open userspace probe location lookup method element. */
2075 ret = mi_lttng_writer_open_element(writer,
2076 mi_lttng_element_userspace_probe_location_lookup_method);
2077 if (ret) {
2078 goto mi_error;
2079 }
2080
2081 /* User space probe location lookup method empty element. */
2082 ret = mi_lttng_writer_open_element(writer, type_element_str);
2083 if (ret) {
2084 goto mi_error;
2085 }
2086
2087 /* Close userspace probe location lookup method element. */
2088 ret = mi_lttng_close_multi_element(writer, 2);
2089 if (ret) {
2090 goto mi_error;
2091 }
2092
2093 ret_code = LTTNG_OK;
2094 goto end;
2095
2096mi_error:
2097 ret_code = LTTNG_ERR_MI_IO_FAIL;
2098end:
2099 return ret_code;
2100}
2101
2102static enum lttng_error_code lttng_userspace_probe_location_tracepoint_mi_serialize(
2103 const struct lttng_userspace_probe_location *location,
2104 struct mi_writer *writer)
2105{
2106 int ret;
2107 enum lttng_error_code ret_code;
2108 const char *probe_name = NULL;
2109 const char *provider_name = NULL;
2110 const char *binary_path = NULL;
2111 const struct lttng_userspace_probe_location_lookup_method
2112 *lookup_method = NULL;
2113
a0377dfe
FD
2114 LTTNG_ASSERT(location);
2115 LTTNG_ASSERT(writer);
6a751b95
JR
2116
2117 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(
2118 location);
2119 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(
2120 location);
2121 binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(
2122 location);
2123 lookup_method = lttng_userspace_probe_location_tracepoint_get_lookup_method(
2124 location);
2125
2126 /* Open userspace probe location tracepoint element. */
2127 ret = mi_lttng_writer_open_element(writer,
2128 mi_lttng_element_userspace_probe_location_tracepoint);
2129 if (ret) {
2130 goto mi_error;
2131 }
2132
2133 /* Probe name. */
2134 ret = mi_lttng_writer_write_element_string(writer,
2135 mi_lttng_element_userspace_probe_location_tracepoint_probe_name,
2136 probe_name);
2137 if (ret) {
2138 goto mi_error;
2139 }
2140
2141 /* Provider name. */
2142 ret = mi_lttng_writer_write_element_string(writer,
2143 mi_lttng_element_userspace_probe_location_tracepoint_provider_name,
2144 provider_name);
2145 if (ret) {
2146 goto mi_error;
2147 }
2148
2149 /* Binary path. */
2150 ret = mi_lttng_writer_write_element_string(writer,
2151 mi_lttng_element_userspace_probe_location_binary_path,
2152 binary_path);
2153 if (ret) {
2154 goto mi_error;
2155 }
2156
2157 /* The lookup method. */
2158 ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize(
2159 lookup_method, writer);
2160 if (ret_code != LTTNG_OK) {
2161 goto end;
2162 }
2163
2164 /* Close userspace probe location tracepoint. */
2165 ret = mi_lttng_writer_close_element(writer);
2166 if (ret) {
2167 goto mi_error;
2168 }
2169
2170 ret_code = LTTNG_OK;
2171 goto end;
2172
2173mi_error:
2174 ret_code = LTTNG_ERR_MI_IO_FAIL;
2175end:
2176 return ret_code;
2177}
2178
2179static enum lttng_error_code lttng_userspace_probe_location_function_mi_serialize(
2180 const struct lttng_userspace_probe_location *location,
2181 struct mi_writer *writer)
2182{
2183 int ret;
2184 enum lttng_error_code ret_code;
2185 const char *function_name = NULL;
2186 const char *binary_path = NULL;
2187 const char *instrumentation_type_str = NULL;
2188 enum lttng_userspace_probe_location_function_instrumentation_type
2189 instrumentation_type;
2190 const struct lttng_userspace_probe_location_lookup_method
2191 *lookup_method = NULL;
2192
a0377dfe
FD
2193 LTTNG_ASSERT(location);
2194 LTTNG_ASSERT(writer);
6a751b95
JR
2195
2196 function_name = lttng_userspace_probe_location_function_get_function_name(
2197 location);
2198 binary_path = lttng_userspace_probe_location_function_get_binary_path(
2199 location);
2200 instrumentation_type =
2201 lttng_userspace_probe_location_function_get_instrumentation_type(
2202 location);
2203 lookup_method = lttng_userspace_probe_location_function_get_lookup_method(
2204 location);
2205
2206 switch (instrumentation_type) {
2207 case LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY:
2208 instrumentation_type_str =
2209 mi_lttng_userspace_probe_location_function_instrumentation_type_entry;
2210 break;
2211 default:
2212 abort();
2213 break;
2214 }
2215
2216 /* Open userspace probe location function element. */
2217 ret = mi_lttng_writer_open_element(writer,
2218 mi_lttng_element_userspace_probe_location_function);
2219 if (ret) {
2220 goto mi_error;
2221 }
2222
2223 /* Function name. */
2224 ret = mi_lttng_writer_write_element_string(writer,
2225 mi_lttng_element_userspace_probe_location_function_name,
2226 function_name);
2227 if (ret) {
2228 goto mi_error;
2229 }
2230
2231 /* Binary path. */
2232 ret = mi_lttng_writer_write_element_string(writer,
2233 mi_lttng_element_userspace_probe_location_binary_path,
2234 binary_path);
2235 if (ret) {
2236 goto mi_error;
2237 }
2238
2239 /* Instrumentation type. */
2240 ret = mi_lttng_writer_write_element_string(writer,
2241 mi_lttng_element_userspace_probe_location_function_instrumentation_type,
2242 instrumentation_type_str);
2243 if (ret) {
2244 goto mi_error;
2245 }
2246
2247 /* The lookup method. */
2248 ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize(
2249 lookup_method, writer);
2250 if (ret_code != LTTNG_OK) {
2251 goto end;
2252 }
2253
2254 /* Close userspace probe location function element. */
2255 ret = mi_lttng_writer_close_element(writer);
2256 if (ret) {
2257 goto mi_error;
2258 }
2259
2260 ret_code = LTTNG_OK;
2261 goto end;
2262
2263mi_error:
2264 ret_code = LTTNG_ERR_MI_IO_FAIL;
2265end:
2266 return ret_code;
2267}
This page took 0.141466 seconds and 4 git commands to generate.