consumerd: send a buffer static sample on flush command
[lttng-tools.git] / src / common / userspace-probe.cpp
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"
c9e313bc
SM
9#include <common/compat/string.hpp>
10#include <common/align.hpp>
11#include <common/error.hpp>
12#include <common/hashtable/hashtable.hpp>
13#include <common/hashtable/utils.hpp>
14#include <common/macros.hpp>
15#include <common/mi-lttng.hpp>
16#include <common/payload-view.hpp>
17#include <common/payload.hpp>
1ce46cfe
JG
18#include <fcntl.h>
19#include <lttng/constant.h>
c9e313bc 20#include <lttng/userspace-probe-internal.hpp>
dfcfa983
JR
21#include <sys/stat.h>
22#include <sys/types.h>
8f14767d 23#include <unistd.h>
1ce46cfe 24
fe489250 25static
2cde0510 26int lttng_userspace_probe_location_function_set_binary_fd_handle(
fe489250 27 struct lttng_userspace_probe_location *location,
2cde0510 28 struct fd_handle *binary_fd_handle);
fe489250
JG
29
30static
2cde0510 31int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
fe489250 32 struct lttng_userspace_probe_location *location,
2cde0510 33 struct fd_handle *binary_fd_handle);
fe489250 34
6a751b95
JR
35static
36enum lttng_error_code lttng_userspace_probe_location_lookup_method_mi_serialize(
37 const struct lttng_userspace_probe_location_lookup_method
38 *method,
39 struct mi_writer *writer);
40
41static
42enum lttng_error_code lttng_userspace_probe_location_tracepoint_mi_serialize(
43 const struct lttng_userspace_probe_location *location,
44 struct mi_writer *writer);
45
46static
47enum lttng_error_code lttng_userspace_probe_location_function_mi_serialize(
48 const struct lttng_userspace_probe_location *location,
49 struct mi_writer *writer);
50
1ce46cfe
JG
51enum lttng_userspace_probe_location_lookup_method_type
52lttng_userspace_probe_location_lookup_method_get_type(
53 const struct lttng_userspace_probe_location_lookup_method *lookup_method)
54{
55 return lookup_method ? lookup_method->type :
56 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_UNKNOWN;
57}
58
59void lttng_userspace_probe_location_lookup_method_destroy(
60 struct lttng_userspace_probe_location_lookup_method *lookup_method)
61{
62 if (!lookup_method){
63 return;
64 }
65
5d21f143 66 free(lookup_method);
1ce46cfe
JG
67}
68
69struct lttng_userspace_probe_location_lookup_method *
70lttng_userspace_probe_location_lookup_method_function_elf_create(void)
71{
72 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
73 struct lttng_userspace_probe_location_lookup_method_elf *elf_method;
74
64803277 75 elf_method = zmalloc<lttng_userspace_probe_location_lookup_method_elf>();
1ce46cfe
JG
76 if (!elf_method) {
77 PERROR("zmalloc");
78 goto end;
79 }
80
81 ret = &elf_method->parent;
82 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
83end:
84 return ret;
85}
86
f4d0bb2e
FD
87struct lttng_userspace_probe_location_lookup_method *
88lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create(void)
89{
90 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
91 struct lttng_userspace_probe_location_lookup_method_sdt *sdt_method;
92
64803277 93 sdt_method = zmalloc<lttng_userspace_probe_location_lookup_method_sdt>();
f4d0bb2e
FD
94 if (!sdt_method) {
95 PERROR("zmalloc");
96 goto end;
97 }
98
99 ret = &sdt_method->parent;
100 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
101end:
102 return ret;
103}
104
1ce46cfe
JG
105enum lttng_userspace_probe_location_type lttng_userspace_probe_location_get_type(
106 const struct lttng_userspace_probe_location *location)
107{
108 return location ? location->type :
109 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN;
110}
111
112static
113void lttng_userspace_probe_location_function_destroy(
114 struct lttng_userspace_probe_location *location)
115{
116 struct lttng_userspace_probe_location_function *location_function = NULL;
117
a0377dfe 118 LTTNG_ASSERT(location);
1ce46cfe 119
0114db0e
JG
120 location_function = lttng::utils::container_of(location,
121 &lttng_userspace_probe_location_function::parent);
1ce46cfe 122
a0377dfe 123 LTTNG_ASSERT(location_function);
1ce46cfe
JG
124
125 free(location_function->function_name);
126 free(location_function->binary_path);
2cde0510 127 fd_handle_put(location_function->binary_fd_handle);
1ce46cfe
JG
128 free(location);
129}
130
f4d0bb2e
FD
131static
132void lttng_userspace_probe_location_tracepoint_destroy(
133 struct lttng_userspace_probe_location *location)
134{
135 struct lttng_userspace_probe_location_tracepoint *location_tracepoint = NULL;
136
a0377dfe 137 LTTNG_ASSERT(location);
f4d0bb2e 138
0114db0e
JG
139 location_tracepoint = lttng::utils::container_of(location,
140 &lttng_userspace_probe_location_tracepoint::parent);
f4d0bb2e 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 =
0114db0e
JG
227 lttng::utils::container_of(
228 location, &lttng_userspace_probe_location_function::parent);
959e3c66
JR
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
0114db0e
JG
246 a = lttng::utils::container_of(_a,
247 &lttng_userspace_probe_location_function::parent);
248 b = lttng::utils::container_of(_b,
249 &lttng_userspace_probe_location_function::parent);
dfcfa983
JR
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
64803277 313 location = zmalloc<lttng_userspace_probe_location_function>();
1ce46cfe
JG
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);
0114db0e
JG
352 struct lttng_userspace_probe_location_tracepoint *tp_location = lttng::utils::container_of(
353 location, &lttng_userspace_probe_location_tracepoint::parent);
959e3c66
JR
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
0114db0e
JG
372 a = lttng::utils::container_of(_a,
373 &lttng_userspace_probe_location_tracepoint::parent);
374 b = lttng::utils::container_of(_b,
375 &lttng_userspace_probe_location_tracepoint::parent);
dfcfa983 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
64803277 450 location = zmalloc<lttng_userspace_probe_location_tracepoint>();
f4d0bb2e
FD
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
64803277 549 elf_method = zmalloc<lttng_userspace_probe_location_lookup_method_elf>();
394357fe
FD
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
64803277 576 sdt_method = zmalloc<lttng_userspace_probe_location_lookup_method_sdt>();
f4d0bb2e
FD
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);
0114db0e
JG
606 function_location = lttng::utils::container_of(
607 location, &lttng_userspace_probe_location_function::parent);
394357fe 608
0114db0e 609 /* Get probe location fields */
cc831309 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);
0114db0e
JG
680 tracepoint_location = lttng::utils::container_of(
681 location, &lttng_userspace_probe_location_tracepoint::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
0114db0e
JG
758 function_location = lttng::utils::container_of(location,
759 &lttng_userspace_probe_location_function::parent);
1ce46cfe
JG
760 ret = function_location->binary_path;
761end:
762 return ret;
763}
764
f4d0bb2e
FD
765const char *lttng_userspace_probe_location_tracepoint_get_binary_path(
766 const struct lttng_userspace_probe_location *location)
767{
768 const char *ret = NULL;
769 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
770
771 if (!location || lttng_userspace_probe_location_get_type(location) !=
772 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
f04a8200 773 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
f4d0bb2e
FD
774 goto end;
775 }
776
0114db0e
JG
777 tracepoint_location = lttng::utils::container_of(location,
778 &lttng_userspace_probe_location_tracepoint::parent);
f4d0bb2e
FD
779 ret = tracepoint_location->binary_path;
780end:
781 return ret;
782}
783
1ce46cfe
JG
784const char *lttng_userspace_probe_location_function_get_function_name(
785 const struct lttng_userspace_probe_location *location)
786{
787 const char *ret = NULL;
788 struct lttng_userspace_probe_location_function *function_location;
789
790 if (!location || lttng_userspace_probe_location_get_type(location) !=
791 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
f04a8200 792 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
1ce46cfe
JG
793 goto end;
794 }
795
0114db0e
JG
796 function_location = lttng::utils::container_of(location,
797 &lttng_userspace_probe_location_function::parent);
1ce46cfe
JG
798 ret = function_location->function_name;
799end:
800 return ret;
801}
802
f4d0bb2e
FD
803const char *lttng_userspace_probe_location_tracepoint_get_probe_name(
804 const struct lttng_userspace_probe_location *location)
805{
806 const char *ret = NULL;
807 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
808
809 if (!location || lttng_userspace_probe_location_get_type(location) !=
810 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
f04a8200 811 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
f4d0bb2e
FD
812 goto end;
813 }
814
0114db0e
JG
815 tracepoint_location = lttng::utils::container_of(location,
816 &lttng_userspace_probe_location_tracepoint::parent);
f4d0bb2e
FD
817 ret = tracepoint_location->probe_name;
818end:
819 return ret;
820}
821
822const char *lttng_userspace_probe_location_tracepoint_get_provider_name(
823 const struct lttng_userspace_probe_location *location)
824{
825 const char *ret = NULL;
826 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
827
828 if (!location || lttng_userspace_probe_location_get_type(location) !=
829 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
f04a8200 830 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
f4d0bb2e
FD
831 goto end;
832 }
833
0114db0e
JG
834 tracepoint_location = lttng::utils::container_of(location,
835 &lttng_userspace_probe_location_tracepoint::parent);
f4d0bb2e
FD
836 ret = tracepoint_location->provider_name;
837end:
838 return ret;
839}
840
1ce46cfe
JG
841int lttng_userspace_probe_location_function_get_binary_fd(
842 const struct lttng_userspace_probe_location *location)
843{
844 int ret = -1;
845 struct lttng_userspace_probe_location_function *function_location;
846
847 if (!location || lttng_userspace_probe_location_get_type(location) !=
848 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
f04a8200 849 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
1ce46cfe
JG
850 goto end;
851 }
852
0114db0e
JG
853 function_location = lttng::utils::container_of(location,
854 &lttng_userspace_probe_location_function::parent);
2cde0510
JG
855 ret = function_location->binary_fd_handle ?
856 fd_handle_get_fd(function_location->binary_fd_handle) : -1;
1ce46cfe
JG
857end:
858 return ret;
859}
860
9d3981b5
JG
861enum lttng_userspace_probe_location_function_instrumentation_type
862lttng_userspace_probe_location_function_get_instrumentation_type(
863 const struct lttng_userspace_probe_location *location)
864{
865 enum lttng_userspace_probe_location_function_instrumentation_type type;
866 struct lttng_userspace_probe_location_function *function_location;
867
868 if (!location || lttng_userspace_probe_location_get_type(location) !=
869 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
f04a8200 870 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
9d3981b5
JG
871 type = LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_UNKNOWN;
872 goto end;
873 }
874
0114db0e
JG
875 function_location = lttng::utils::container_of(location,
876 &lttng_userspace_probe_location_function::parent);
9d3981b5
JG
877 type = function_location->instrumentation_type;
878end:
879 return type;
880}
881
882enum lttng_userspace_probe_location_status
883lttng_userspace_probe_location_function_set_instrumentation_type(
884 const struct lttng_userspace_probe_location *location,
885 enum lttng_userspace_probe_location_function_instrumentation_type instrumentation_type)
886{
887 enum lttng_userspace_probe_location_status status =
888 LTTNG_USERSPACE_PROBE_LOCATION_STATUS_OK;
889 struct lttng_userspace_probe_location_function *function_location;
890
891 if (!location || lttng_userspace_probe_location_get_type(location) !=
892 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION ||
893 instrumentation_type !=
894 LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY) {
f04a8200 895 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
9d3981b5
JG
896 status = LTTNG_USERSPACE_PROBE_LOCATION_STATUS_INVALID;
897 goto end;
898 }
899
0114db0e
JG
900 function_location = lttng::utils::container_of(location,
901 &lttng_userspace_probe_location_function::parent);
9d3981b5
JG
902 function_location->instrumentation_type = instrumentation_type;
903end:
904 return status;
905}
906
f4d0bb2e
FD
907int lttng_userspace_probe_location_tracepoint_get_binary_fd(
908 const struct lttng_userspace_probe_location *location)
909{
910 int ret = -1;
911 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
912
913 if (!location || lttng_userspace_probe_location_get_type(location) !=
914 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
f04a8200 915 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
f4d0bb2e
FD
916 goto end;
917 }
918
0114db0e
JG
919 tracepoint_location = lttng::utils::container_of(location,
920 &lttng_userspace_probe_location_tracepoint::parent);
2cde0510
JG
921 ret = tracepoint_location->binary_fd_handle ?
922 fd_handle_get_fd(tracepoint_location->binary_fd_handle) : -1;
f4d0bb2e
FD
923end:
924 return ret;
925}
926
1ce46cfe
JG
927static struct lttng_userspace_probe_location_lookup_method *
928lttng_userspace_probe_location_function_get_lookup_method(
929 const struct lttng_userspace_probe_location *location)
930{
931 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
932
933 if (!location || lttng_userspace_probe_location_get_type(location) !=
934 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
f04a8200 935 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
1ce46cfe
JG
936 goto end;
937 }
938
939 ret = location->lookup_method;
940end:
941 return ret;
942}
943
f4d0bb2e
FD
944static struct lttng_userspace_probe_location_lookup_method *
945lttng_userspace_probe_location_tracepoint_get_lookup_method(
946 const struct lttng_userspace_probe_location *location)
947{
948 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
949
950 if (!location || lttng_userspace_probe_location_get_type(location) !=
951 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT) {
f04a8200 952 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
f4d0bb2e
FD
953 goto end;
954 }
955
956 ret = location->lookup_method;
957end:
958 return ret;
959}
960
87597c2c 961const struct lttng_userspace_probe_location_lookup_method *
1ce46cfe
JG
962lttng_userspace_probe_location_get_lookup_method(
963 const struct lttng_userspace_probe_location *location)
964{
965 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
966
a0377dfe 967 LTTNG_ASSERT(location);
1ce46cfe
JG
968 switch (location->type) {
969 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
970 ret = lttng_userspace_probe_location_function_get_lookup_method(
971 location);
972 break;
f4d0bb2e
FD
973 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
974 ret = lttng_userspace_probe_location_tracepoint_get_lookup_method(
975 location);
976 break;
1ce46cfe
JG
977 default:
978 ERR("Unknowned lookup method.");
979 break;
980 }
981 return ret;
982}
983
984static
985int lttng_userspace_probe_location_lookup_method_serialize(
986 struct lttng_userspace_probe_location_lookup_method *method,
e368fb43 987 struct lttng_payload *payload)
1ce46cfe
JG
988{
989 int ret;
990 struct lttng_userspace_probe_location_lookup_method_comm
991 lookup_method_comm;
992
993 lookup_method_comm.type = (int8_t) (method ? method->type :
994 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT);
e368fb43
JG
995 if (payload) {
996 ret = lttng_dynamic_buffer_append(&payload->buffer, &lookup_method_comm,
1ce46cfe
JG
997 sizeof(lookup_method_comm));
998 if (ret) {
999 goto end;
1000 }
1001 }
f4d0bb2e
FD
1002 ret = sizeof(lookup_method_comm);
1003end:
1004 return ret;
1005}
1006
1007static
1008int lttng_userspace_probe_location_function_serialize(
1009 const struct lttng_userspace_probe_location *location,
e368fb43 1010 struct lttng_payload *payload)
f4d0bb2e
FD
1011{
1012 int ret;
1013 size_t function_name_len, binary_path_len;
1014 struct lttng_userspace_probe_location_function *location_function;
1015 struct lttng_userspace_probe_location_function_comm location_function_comm;
1016
a0377dfe
FD
1017 LTTNG_ASSERT(location);
1018 LTTNG_ASSERT(lttng_userspace_probe_location_get_type(location) ==
f4d0bb2e
FD
1019 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1020
0114db0e
JG
1021 location_function = lttng::utils::container_of(location,
1022 &lttng_userspace_probe_location_function::parent);
f4d0bb2e
FD
1023 if (!location_function->function_name || !location_function->binary_path) {
1024 ret = -LTTNG_ERR_INVALID;
1025 goto end;
1026 }
1027
2cde0510 1028 if (payload && !location_function->binary_fd_handle) {
f4d0bb2e
FD
1029 ret = -LTTNG_ERR_INVALID;
1030 goto end;
1031 }
1032
f4d0bb2e
FD
1033 function_name_len = strlen(location_function->function_name);
1034 if (function_name_len == 0) {
1035 ret = -LTTNG_ERR_INVALID;
1036 goto end;
1037 }
1038 binary_path_len = strlen(location_function->binary_path);
1039 if (binary_path_len == 0) {
1040 ret = -LTTNG_ERR_INVALID;
1041 goto end;
1042 }
1043
1044 location_function_comm.function_name_len = function_name_len + 1;
1045 location_function_comm.binary_path_len = binary_path_len + 1;
1046
e368fb43
JG
1047 if (payload) {
1048 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1049 &location_function_comm,
1050 sizeof(location_function_comm));
1051 if (ret) {
1052 ret = -LTTNG_ERR_INVALID;
1053 goto end;
1054 }
e368fb43 1055 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1056 location_function->function_name,
1057 location_function_comm.function_name_len);
1058 if (ret) {
1059 ret = -LTTNG_ERR_INVALID;
1060 goto end;
1061 }
e368fb43 1062 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1063 location_function->binary_path,
1064 location_function_comm.binary_path_len);
1065 if (ret) {
1066 ret = -LTTNG_ERR_INVALID;
1067 goto end;
1068 }
fe489250 1069 ret = lttng_payload_push_fd_handle(
2cde0510 1070 payload, location_function->binary_fd_handle);
e368fb43
JG
1071 if (ret) {
1072 ret = -LTTNG_ERR_INVALID;
1073 goto end;
1074 }
f4d0bb2e
FD
1075 }
1076 ret = sizeof(location_function_comm) +
1077 location_function_comm.function_name_len +
1078 location_function_comm.binary_path_len;
1ce46cfe
JG
1079end:
1080 return ret;
1081}
1082
1083static
f4d0bb2e 1084int lttng_userspace_probe_location_tracepoint_serialize(
1ce46cfe 1085 const struct lttng_userspace_probe_location *location,
e368fb43 1086 struct lttng_payload *payload)
1ce46cfe
JG
1087{
1088 int ret;
f4d0bb2e
FD
1089 size_t probe_name_len, provider_name_len, binary_path_len;
1090 struct lttng_userspace_probe_location_tracepoint *location_tracepoint;
1091 struct lttng_userspace_probe_location_tracepoint_comm location_tracepoint_comm;
1ce46cfe 1092
a0377dfe
FD
1093 LTTNG_ASSERT(location);
1094 LTTNG_ASSERT(lttng_userspace_probe_location_get_type(location) ==
f4d0bb2e 1095 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
1ce46cfe 1096
0114db0e
JG
1097 location_tracepoint = lttng::utils::container_of(location,
1098 &lttng_userspace_probe_location_tracepoint::parent);
f4d0bb2e
FD
1099 if (!location_tracepoint->probe_name ||
1100 !location_tracepoint->provider_name ||
1101 !location_tracepoint->binary_path) {
1ce46cfe
JG
1102 ret = -LTTNG_ERR_INVALID;
1103 goto end;
1104 }
1105
2cde0510 1106 if (payload && !location_tracepoint->binary_fd_handle) {
1ce46cfe
JG
1107 ret = -LTTNG_ERR_INVALID;
1108 goto end;
1109 }
1110
f4d0bb2e
FD
1111 probe_name_len = strlen(location_tracepoint->probe_name);
1112 if (probe_name_len == 0) {
1ce46cfe
JG
1113 ret = -LTTNG_ERR_INVALID;
1114 goto end;
1115 }
f4d0bb2e
FD
1116
1117 provider_name_len = strlen(location_tracepoint->provider_name);
1118 if (provider_name_len == 0) {
1119 ret = -LTTNG_ERR_INVALID;
1120 goto end;
1121 }
1122
1123 binary_path_len = strlen(location_tracepoint->binary_path);
1ce46cfe
JG
1124 if (binary_path_len == 0) {
1125 ret = -LTTNG_ERR_INVALID;
1126 goto end;
1127 }
1128
f4d0bb2e
FD
1129 location_tracepoint_comm.probe_name_len = probe_name_len + 1;
1130 location_tracepoint_comm.provider_name_len = provider_name_len + 1;
1131 location_tracepoint_comm.binary_path_len = binary_path_len + 1;
1ce46cfe 1132
e368fb43
JG
1133 if (payload) {
1134 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1135 &location_tracepoint_comm,
1136 sizeof(location_tracepoint_comm));
1ce46cfe
JG
1137 if (ret) {
1138 ret = -LTTNG_ERR_INVALID;
1139 goto end;
1140 }
e368fb43 1141 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1142 location_tracepoint->probe_name,
1143 location_tracepoint_comm.probe_name_len);
1ce46cfe
JG
1144 if (ret) {
1145 ret = -LTTNG_ERR_INVALID;
1146 goto end;
1147 }
e368fb43 1148 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1149 location_tracepoint->provider_name,
1150 location_tracepoint_comm.provider_name_len);
1151 if (ret) {
1152 ret = -LTTNG_ERR_INVALID;
1153 goto end;
1154 }
e368fb43 1155 ret = lttng_dynamic_buffer_append(&payload->buffer,
f4d0bb2e
FD
1156 location_tracepoint->binary_path,
1157 location_tracepoint_comm.binary_path_len);
1ce46cfe
JG
1158 if (ret) {
1159 ret = -LTTNG_ERR_INVALID;
1160 goto end;
1161 }
fe489250 1162 ret = lttng_payload_push_fd_handle(
2cde0510 1163 payload, location_tracepoint->binary_fd_handle);
e368fb43
JG
1164 if (ret) {
1165 ret = -LTTNG_ERR_INVALID;
1166 goto end;
1167 }
1ce46cfe 1168 }
e368fb43 1169
f4d0bb2e
FD
1170 ret = sizeof(location_tracepoint_comm) +
1171 location_tracepoint_comm.probe_name_len +
1172 location_tracepoint_comm.provider_name_len +
1173 location_tracepoint_comm.binary_path_len;
1ce46cfe
JG
1174end:
1175 return ret;
1176}
1177
1ce46cfe
JG
1178int lttng_userspace_probe_location_serialize(
1179 const struct lttng_userspace_probe_location *location,
e368fb43 1180 struct lttng_payload *payload)
1ce46cfe
JG
1181{
1182 int ret, buffer_use = 0;
1183 struct lttng_userspace_probe_location_comm location_generic_comm;
1184
1185 if (!location) {
f04a8200 1186 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
1ce46cfe
JG
1187 ret = -LTTNG_ERR_INVALID;
1188 goto end;
1189 }
1190
56f0bc67
JG
1191 memset(&location_generic_comm, 0, sizeof(location_generic_comm));
1192
1ce46cfe 1193 location_generic_comm.type = (int8_t) location->type;
e368fb43
JG
1194 if (payload) {
1195 ret = lttng_dynamic_buffer_append(&payload->buffer,
1196 &location_generic_comm,
1ce46cfe
JG
1197 sizeof(location_generic_comm));
1198 if (ret) {
1199 goto end;
1200 }
1201 }
1202 buffer_use += sizeof(location_generic_comm);
1203
1204 switch (lttng_userspace_probe_location_get_type(location)) {
1205 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1206 ret = lttng_userspace_probe_location_function_serialize(
e368fb43 1207 location, payload);
1ce46cfe 1208 break;
f4d0bb2e
FD
1209 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1210 ret = lttng_userspace_probe_location_tracepoint_serialize(
e368fb43 1211 location, payload);
f4d0bb2e 1212 break;
1ce46cfe
JG
1213 default:
1214 ERR("Unsupported probe location type");
1215 ret = -LTTNG_ERR_INVALID;
1216 goto end;
1217 }
1218 if (ret < 0) {
1219 goto end;
1220 }
1221 buffer_use += ret;
1222
1223 ret = lttng_userspace_probe_location_lookup_method_serialize(
e368fb43 1224 location->lookup_method, payload);
1ce46cfe
JG
1225 if (ret < 0) {
1226 goto end;
1227 }
1228 ret += buffer_use;
1229end:
1230 return ret;
1231}
1232
1233static
e368fb43
JG
1234int lttng_userspace_probe_location_function_create_from_payload(
1235 struct lttng_payload_view *view,
1ce46cfe
JG
1236 struct lttng_userspace_probe_location **location)
1237{
1238 struct lttng_userspace_probe_location_function_comm *location_function_comm;
1239 const char *function_name_src, *binary_path_src;
1240 char *function_name = NULL, *binary_path = NULL;
1241 int ret = 0;
e368fb43 1242 size_t expected_size;
2cde0510 1243 struct fd_handle *binary_fd_handle = lttng_payload_view_pop_fd_handle(view);
1ce46cfe 1244
a0377dfe 1245 LTTNG_ASSERT(location);
1ce46cfe 1246
e368fb43
JG
1247 if (view->buffer.size < sizeof(*location_function_comm)) {
1248 ret = -LTTNG_ERR_INVALID;
1249 goto end;
1250 }
1251
1ce46cfe 1252 location_function_comm =
e368fb43 1253 (typeof(location_function_comm)) view->buffer.data;
1ce46cfe 1254
e368fb43 1255 expected_size = sizeof(*location_function_comm) +
1ce46cfe
JG
1256 location_function_comm->function_name_len +
1257 location_function_comm->binary_path_len;
1258
e368fb43 1259 if (view->buffer.size < expected_size) {
1ce46cfe
JG
1260 ret = -LTTNG_ERR_INVALID;
1261 goto end;
1262 }
1263
e368fb43 1264 function_name_src = view->buffer.data + sizeof(*location_function_comm);
1ce46cfe
JG
1265 binary_path_src = function_name_src +
1266 location_function_comm->function_name_len;
1267
48c24aea
JG
1268 if (!lttng_buffer_view_contains_string(&view->buffer, function_name_src,
1269 location_function_comm->function_name_len)) {
1ce46cfe
JG
1270 ret = -LTTNG_ERR_INVALID;
1271 goto end;
1272 }
48c24aea
JG
1273
1274 if (!lttng_buffer_view_contains_string(&view->buffer, binary_path_src,
1275 location_function_comm->binary_path_len)) {
1ce46cfe
JG
1276 ret = -LTTNG_ERR_INVALID;
1277 goto end;
1278 }
1279
1280 function_name = lttng_strndup(function_name_src, LTTNG_SYMBOL_NAME_LEN);
1281 if (!function_name) {
1282 PERROR("lttng_strndup");
2aa28610 1283 ret = -LTTNG_ERR_NOMEM;
1ce46cfe
JG
1284 goto end;
1285 }
1286
1287 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
1288 if (!binary_path) {
1289 PERROR("lttng_strndup");
2aa28610 1290 ret = -LTTNG_ERR_NOMEM;
1ce46cfe
JG
1291 goto end;
1292 }
1293
1294 *location = lttng_userspace_probe_location_function_create_no_check(
1295 binary_path, function_name, NULL, false);
1296 if (!(*location)) {
1297 ret = -LTTNG_ERR_INVALID;
1298 goto end;
1299 }
1300
2cde0510
JG
1301 ret = lttng_userspace_probe_location_function_set_binary_fd_handle(
1302 *location, binary_fd_handle);
e368fb43 1303 if (ret) {
e368fb43
JG
1304 ret = -LTTNG_ERR_INVALID;
1305 goto end;
1306 }
1307
1ce46cfe
JG
1308 ret = (int) expected_size;
1309end:
2cde0510 1310 fd_handle_put(binary_fd_handle);
1ce46cfe
JG
1311 free(function_name);
1312 free(binary_path);
1313 return ret;
1314}
1315
f4d0bb2e 1316static
e368fb43
JG
1317int lttng_userspace_probe_location_tracepoint_create_from_payload(
1318 struct lttng_payload_view *view,
f4d0bb2e
FD
1319 struct lttng_userspace_probe_location **location)
1320{
1321 struct lttng_userspace_probe_location_tracepoint_comm *location_tracepoint_comm;
1322 const char *probe_name_src, *provider_name_src, *binary_path_src;
1323 char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
1324 int ret = 0;
e368fb43 1325 size_t expected_size;
2cde0510 1326 struct fd_handle *binary_fd_handle = lttng_payload_view_pop_fd_handle(view);
f4d0bb2e 1327
a0377dfe 1328 LTTNG_ASSERT(location);
f4d0bb2e 1329
2cde0510 1330 if (!binary_fd_handle) {
e368fb43
JG
1331 ret = -LTTNG_ERR_INVALID;
1332 goto end;
1333 }
1334
1335 if (view->buffer.size < sizeof(*location_tracepoint_comm)) {
1336 ret = -LTTNG_ERR_INVALID;
1337 goto end;
1338 }
1339
f4d0bb2e 1340 location_tracepoint_comm =
e368fb43 1341 (typeof(location_tracepoint_comm)) view->buffer.data;
f4d0bb2e 1342
e368fb43 1343 expected_size = sizeof(*location_tracepoint_comm) +
f4d0bb2e
FD
1344 location_tracepoint_comm->probe_name_len +
1345 location_tracepoint_comm->provider_name_len +
1346 location_tracepoint_comm->binary_path_len;
1347
e368fb43 1348 if (view->buffer.size < expected_size) {
f4d0bb2e
FD
1349 ret = -LTTNG_ERR_INVALID;
1350 goto end;
1351 }
1352
e368fb43 1353 probe_name_src = view->buffer.data + sizeof(*location_tracepoint_comm);
f4d0bb2e
FD
1354 provider_name_src = probe_name_src +
1355 location_tracepoint_comm->probe_name_len;
1356 binary_path_src = provider_name_src +
1357 location_tracepoint_comm->provider_name_len;
1358
48c24aea
JG
1359 if (!lttng_buffer_view_contains_string(&view->buffer, probe_name_src,
1360 location_tracepoint_comm->probe_name_len)) {
f4d0bb2e
FD
1361 ret = -LTTNG_ERR_INVALID;
1362 goto end;
1363 }
1364
48c24aea
JG
1365 if (!lttng_buffer_view_contains_string(&view->buffer, provider_name_src,
1366 location_tracepoint_comm->provider_name_len)) {
f4d0bb2e
FD
1367 ret = -LTTNG_ERR_INVALID;
1368 goto end;
1369 }
1370
48c24aea
JG
1371 if (!lttng_buffer_view_contains_string(&view->buffer, binary_path_src,
1372 location_tracepoint_comm->binary_path_len)) {
f4d0bb2e
FD
1373 ret = -LTTNG_ERR_INVALID;
1374 goto end;
1375 }
1376
1377 probe_name = lttng_strndup(probe_name_src, LTTNG_SYMBOL_NAME_LEN);
1378 if (!probe_name) {
c21e883d
JG
1379 PERROR("Failed to allocate probe name");
1380 ret = -LTTNG_ERR_INVALID;
f4d0bb2e
FD
1381 goto end;
1382 }
1383 provider_name = lttng_strndup(provider_name_src, LTTNG_SYMBOL_NAME_LEN);
1384 if (!provider_name) {
c21e883d
JG
1385 PERROR("Failed to allocate provider name");
1386 ret = -LTTNG_ERR_INVALID;
f4d0bb2e
FD
1387 goto end;
1388 }
1389
b45a2969 1390 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
f4d0bb2e 1391 if (!binary_path) {
c21e883d
JG
1392 PERROR("Failed to allocate binary path");
1393 ret = -LTTNG_ERR_INVALID;
f4d0bb2e
FD
1394 goto end;
1395 }
1396
1397 *location = lttng_userspace_probe_location_tracepoint_create_no_check(
1398 binary_path, provider_name, probe_name, NULL, false);
1399 if (!(*location)) {
1400 ret = -LTTNG_ERR_INVALID;
1401 goto end;
1402 }
1403
2cde0510
JG
1404 ret = lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
1405 *location, binary_fd_handle);
e368fb43 1406 if (ret) {
e368fb43
JG
1407 ret = -LTTNG_ERR_INVALID;
1408 goto end;
1409 }
1410
f4d0bb2e
FD
1411 ret = (int) expected_size;
1412end:
2cde0510 1413 fd_handle_put(binary_fd_handle);
f4d0bb2e
FD
1414 free(probe_name);
1415 free(provider_name);
1416 free(binary_path);
1417 return ret;
1418}
1419
1ce46cfe 1420static
e368fb43
JG
1421int lttng_userspace_probe_location_lookup_method_create_from_payload(
1422 struct lttng_payload_view *view,
1ce46cfe
JG
1423 struct lttng_userspace_probe_location_lookup_method **lookup_method)
1424{
1425 int ret;
1426 struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
1427 enum lttng_userspace_probe_location_lookup_method_type type;
1428
a0377dfe
FD
1429 LTTNG_ASSERT(view);
1430 LTTNG_ASSERT(lookup_method);
1ce46cfe 1431
e368fb43 1432 if (view->buffer.size < sizeof(*lookup_comm)) {
1ce46cfe
JG
1433 ret = -LTTNG_ERR_INVALID;
1434 goto end;
1435 }
1436
e368fb43 1437 lookup_comm = (typeof(lookup_comm)) view->buffer.data;
1ce46cfe
JG
1438 type = (enum lttng_userspace_probe_location_lookup_method_type)
1439 lookup_comm->type;
1440 switch (type) {
1441 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
1442 *lookup_method = NULL;
1443 break;
1444 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
1445 *lookup_method =
1446 lttng_userspace_probe_location_lookup_method_function_elf_create();
1447 if (!(*lookup_method)) {
1448 ret = -LTTNG_ERR_INVALID;
1449 goto end;
1450 }
1451 break;
f4d0bb2e
FD
1452 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
1453 *lookup_method =
1454 lttng_userspace_probe_location_lookup_method_tracepoint_sdt_create();
1455 if (!(*lookup_method)) {
1456 ret = -LTTNG_ERR_INVALID;
1457 goto end;
1458 }
1459 break;
1ce46cfe
JG
1460 default:
1461 ret = -LTTNG_ERR_INVALID;
1462 goto end;
1463 }
1464
1465 ret = sizeof(*lookup_comm);
1466end:
1467 return ret;
1468}
1469
e368fb43
JG
1470int lttng_userspace_probe_location_create_from_payload(
1471 struct lttng_payload_view *view,
1ce46cfe
JG
1472 struct lttng_userspace_probe_location **location)
1473{
1474 struct lttng_userspace_probe_location_lookup_method *lookup_method;
1ce46cfe 1475 enum lttng_userspace_probe_location_type type;
1ce46cfe
JG
1476 int consumed = 0;
1477 int ret;
3e6e0df2
JG
1478 struct lttng_userspace_probe_location_comm *probe_location_comm;
1479 struct lttng_payload_view probe_location_comm_view =
1480 lttng_payload_view_from_view(
1481 view, 0, sizeof(*probe_location_comm));
1ce46cfe 1482
a0377dfe
FD
1483 LTTNG_ASSERT(view);
1484 LTTNG_ASSERT(location);
1ce46cfe
JG
1485
1486 lookup_method = NULL;
1487
3e6e0df2 1488 if (!lttng_payload_view_is_valid(&probe_location_comm_view)) {
1ce46cfe
JG
1489 ret = -LTTNG_ERR_INVALID;
1490 goto end;
1491 }
1492
3e6e0df2 1493 probe_location_comm = (typeof(probe_location_comm)) probe_location_comm_view.buffer.data;
1ce46cfe
JG
1494 type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
1495 consumed += sizeof(*probe_location_comm);
1496
1497 switch (type) {
1498 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1499 {
e368fb43
JG
1500 struct lttng_payload_view location_view =
1501 lttng_payload_view_from_view(
1502 view, consumed, -1);
1ce46cfe 1503
e368fb43
JG
1504 ret = lttng_userspace_probe_location_function_create_from_payload(
1505 &location_view, location);
1ce46cfe
JG
1506 if (ret < 0) {
1507 goto end;
1508 }
1509 break;
1510 }
f4d0bb2e
FD
1511 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1512 {
e368fb43
JG
1513 struct lttng_payload_view location_view =
1514 lttng_payload_view_from_view(view, consumed, -1);
f4d0bb2e 1515
e368fb43
JG
1516 ret = lttng_userspace_probe_location_tracepoint_create_from_payload(
1517 &location_view, location);
f4d0bb2e
FD
1518 if (ret < 0) {
1519 goto end;
1520 }
1521 break;
1522 }
1ce46cfe
JG
1523 default:
1524 ret = -LTTNG_ERR_INVALID;
1525 goto end;
1526 }
1527
1528 consumed += ret;
e368fb43 1529 if (view->buffer.size <= consumed) {
1ce46cfe
JG
1530 ret = -LTTNG_ERR_INVALID;
1531 goto end;
1532 }
1533
e368fb43
JG
1534 {
1535 struct lttng_payload_view lookup_method_view =
1536 lttng_payload_view_from_view(
1537 view, consumed, -1);
1538
1539 ret = lttng_userspace_probe_location_lookup_method_create_from_payload(
1540 &lookup_method_view, &lookup_method);
1541 }
1ce46cfe
JG
1542 if (ret < 0) {
1543 ret = -LTTNG_ERR_INVALID;
1544 goto end;
1545 }
1546
a0377dfe 1547 LTTNG_ASSERT(lookup_method);
1ce46cfe
JG
1548 (*location)->lookup_method = lookup_method;
1549 lookup_method = NULL;
1550 ret += consumed;
1551end:
1552 return ret;
1553}
1554
fe489250 1555static
2cde0510 1556int lttng_userspace_probe_location_function_set_binary_fd_handle(
fe489250 1557 struct lttng_userspace_probe_location *location,
a6bc4ca9 1558 struct fd_handle *binary_fd)
1ce46cfe
JG
1559{
1560 int ret = 0;
1561 struct lttng_userspace_probe_location_function *function_location;
1562
a0377dfe
FD
1563 LTTNG_ASSERT(location);
1564 LTTNG_ASSERT(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
1ce46cfe 1565
0114db0e
JG
1566 function_location = lttng::utils::container_of(location,
1567 &lttng_userspace_probe_location_function::parent);
2cde0510 1568 fd_handle_put(function_location->binary_fd_handle);
fe489250 1569 fd_handle_get(binary_fd);
2cde0510 1570 function_location->binary_fd_handle = binary_fd;
1ce46cfe
JG
1571 return ret;
1572}
1573
fe489250 1574static
2cde0510 1575int lttng_userspace_probe_location_tracepoint_set_binary_fd_handle(
fe489250
JG
1576 struct lttng_userspace_probe_location *location,
1577 struct fd_handle *binary_fd)
f4d0bb2e
FD
1578{
1579 int ret = 0;
1580 struct lttng_userspace_probe_location_tracepoint *tracepoint_location;
1581
a0377dfe
FD
1582 LTTNG_ASSERT(location);
1583 LTTNG_ASSERT(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT);
f4d0bb2e 1584
0114db0e
JG
1585 tracepoint_location = lttng::utils::container_of(location,
1586 &lttng_userspace_probe_location_tracepoint::parent);
2cde0510 1587 fd_handle_put(tracepoint_location->binary_fd_handle);
fe489250 1588 fd_handle_get(binary_fd);
2cde0510 1589 tracepoint_location->binary_fd_handle = binary_fd;
f4d0bb2e
FD
1590 return ret;
1591}
1592
1ce46cfe
JG
1593static
1594int lttng_userspace_probe_location_function_flatten(
1595 const struct lttng_userspace_probe_location *location,
1596 struct lttng_dynamic_buffer *buffer)
1597{
1598 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method;
1599 struct lttng_userspace_probe_location_function *probe_function;
1600 struct lttng_userspace_probe_location_function flat_probe;
1601 size_t function_name_len, binary_path_len;
1602 size_t padding_needed = 0;
1603 char *flat_probe_start;
1604 int storage_needed = 0;
1605 int ret;
1606
a0377dfe 1607 LTTNG_ASSERT(location);
1ce46cfe
JG
1608
1609 if (location->lookup_method && location->lookup_method->type !=
1610 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF) {
1611 ret = -LTTNG_ERR_INVALID;
1612 goto end;
1613 }
1614
0114db0e
JG
1615 probe_function = lttng::utils::container_of(location,
1616 &lttng_userspace_probe_location_function::parent);
a0377dfe
FD
1617 LTTNG_ASSERT(probe_function->function_name);
1618 LTTNG_ASSERT(probe_function->binary_path);
1ce46cfe
JG
1619
1620 storage_needed +=
1621 sizeof(struct lttng_userspace_probe_location_function);
1622 function_name_len = strlen(probe_function->function_name) + 1;
1623 binary_path_len = strlen(probe_function->binary_path) + 1;
1624 storage_needed += function_name_len + binary_path_len;
1625
1626 /*
1627 * The lookup method is aligned to 64-bit within the buffer.
1628 * This is needed even if there is no lookup method since
1629 * the next structure in the buffer probably needs to be
1630 * aligned too (depending on the arch).
1631 */
1cbd136b 1632 padding_needed = lttng_align_ceil(storage_needed, sizeof(uint64_t)) - storage_needed;
1ce46cfe
JG
1633 storage_needed += padding_needed;
1634
1635 if (location->lookup_method) {
1636 /* NOTE: elf look-up method is assumed here. */
1637 storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1638 }
1639
1640 if (!buffer) {
1641 ret = storage_needed;
1642 goto end;
1643 }
1644
1645 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1646 ret = lttng_dynamic_buffer_set_capacity(buffer,
1647 buffer->size + storage_needed);
1648 if (ret) {
1649 goto end;
1650 }
1651 }
1652
1653 memset(&flat_probe, 0, sizeof(flat_probe));
1654
1655 flat_probe_start = buffer->data + buffer->size;
1656 flat_probe.parent.type = location->type;
1657 /*
1658 * The lookup method, if present, is the last element in the flat
1659 * representation of the probe.
1660 */
1661 if (location->lookup_method) {
1662 flat_probe.parent.lookup_method =
1663 (struct lttng_userspace_probe_location_lookup_method *)
1664 (flat_probe_start + sizeof(flat_probe) +
1665 function_name_len + binary_path_len + padding_needed);
1666 } else {
1667 flat_probe.parent.lookup_method = NULL;
1668 }
1669
1670 flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
1671 flat_probe.binary_path = flat_probe.function_name + function_name_len;
2cde0510 1672 flat_probe.binary_fd_handle = NULL;
1ce46cfe
JG
1673 ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
1674 sizeof(flat_probe));
1675 if (ret) {
1676 goto end;
1677 }
1678
1679 ret = lttng_dynamic_buffer_append(buffer,
1680 probe_function->function_name, function_name_len);
1681 if (ret) {
1682 goto end;
1683 }
1684 ret = lttng_dynamic_buffer_append(buffer,
1685 probe_function->binary_path, binary_path_len);
1686 if (ret) {
1687 goto end;
1688 }
1689
1690 /* Insert padding before the lookup method. */
1691 ret = lttng_dynamic_buffer_set_size(buffer,
1692 buffer->size + padding_needed);
1693 if (ret) {
1694 goto end;
1695 }
1696
1697 if (!location->lookup_method) {
1698 /* Not an error, the default method is used. */
1699 ret = storage_needed;
1700 goto end;
1701 }
1702
1703 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1704 flat_lookup_method.parent.type =
1705 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
1706 ret = lttng_dynamic_buffer_append(buffer,
1707 &flat_lookup_method, sizeof(flat_lookup_method));
1708 if (ret) {
1709 goto end;
1710 }
1711 ret = storage_needed;
1712end:
1713 return ret;
1714}
1715
f4d0bb2e
FD
1716static
1717int lttng_userspace_probe_location_tracepoint_flatten(
1718 const struct lttng_userspace_probe_location *location,
1719 struct lttng_dynamic_buffer *buffer)
1720{
1721 struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method;
1722 struct lttng_userspace_probe_location_tracepoint *probe_tracepoint;
1723 struct lttng_userspace_probe_location_tracepoint flat_probe;
1724 size_t probe_name_len, provider_name_len, binary_path_len;
1725 size_t padding_needed = 0;
1726 int storage_needed = 0;
1727 char *flat_probe_start;
1728 int ret = 0;
1729
a0377dfe 1730 LTTNG_ASSERT(location);
f4d0bb2e
FD
1731
1732 /* Only SDT tracepoints are supported at the moment */
1733 if (location->lookup_method && location->lookup_method->type !=
1734 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT) {
1735 ret = -LTTNG_ERR_INVALID;
1736 goto end;
1737 }
0114db0e
JG
1738 probe_tracepoint = lttng::utils::container_of(location,
1739 &lttng_userspace_probe_location_tracepoint::parent);
a0377dfe
FD
1740 LTTNG_ASSERT(probe_tracepoint->probe_name);
1741 LTTNG_ASSERT(probe_tracepoint->provider_name);
1742 LTTNG_ASSERT(probe_tracepoint->binary_path);
f4d0bb2e
FD
1743
1744 /* Compute the storage space needed to flatten the probe location */
1745 storage_needed += sizeof(struct lttng_userspace_probe_location_tracepoint);
1746
1747 probe_name_len = strlen(probe_tracepoint->probe_name) + 1;
1748 provider_name_len = strlen(probe_tracepoint->provider_name) + 1;
1749 binary_path_len = strlen(probe_tracepoint->binary_path) + 1;
1750
1751 storage_needed += probe_name_len + provider_name_len + binary_path_len;
1752
1753 /*
1754 * The lookup method is aligned to 64-bit within the buffer.
1755 * This is needed even if there is no lookup method since
1756 * the next structure in the buffer probably needs to be
1757 * aligned too (depending on the arch).
1758 */
1cbd136b 1759 padding_needed = lttng_align_ceil(storage_needed, sizeof(uint64_t)) - storage_needed;
f4d0bb2e
FD
1760 storage_needed += padding_needed;
1761
1762 if (location->lookup_method) {
1763 /* NOTE: elf look-up method is assumed here. */
1764 storage_needed +=
1765 sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
1766 }
1767
1768 /*
1769 * If the caller set buffer to NULL, return the size of the needed buffer.
1770 */
1771 if (!buffer) {
1772 ret = storage_needed;
1773 goto end;
1774 }
1775
1776 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
1777 ret = lttng_dynamic_buffer_set_capacity(buffer,
1778 buffer->size + storage_needed);
1779 if (ret) {
1780 goto end;
1781 }
1782 }
1783
1784 memset(&flat_probe, 0, sizeof(flat_probe));
1785
1786 flat_probe_start = buffer->data + buffer->size;
1787 flat_probe.parent.type = location->type;
1788
1789 /*
1790 * The lookup method, if present, is the last element in the flat
1791 * representation of the probe.
1792 */
1793 if (location->lookup_method) {
1794 flat_probe.parent.lookup_method =
1795 (struct lttng_userspace_probe_location_lookup_method *)
1796 (flat_probe_start + sizeof(flat_probe) +
1797 probe_name_len + provider_name_len +
1798 binary_path_len + padding_needed);
1799 } else {
1800 flat_probe.parent.lookup_method = NULL;
1801 }
1802
1803 flat_probe.probe_name = flat_probe_start + sizeof(flat_probe);
1804 flat_probe.provider_name = flat_probe.probe_name + probe_name_len;
1805 flat_probe.binary_path = flat_probe.provider_name + provider_name_len;
2cde0510 1806 flat_probe.binary_fd_handle = NULL;
f4d0bb2e
FD
1807 ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe));
1808 if (ret) {
1809 goto end;
1810 }
1811
1812 /* Append all the fields to the buffer */
1813 ret = lttng_dynamic_buffer_append(buffer,
1814 probe_tracepoint->probe_name, probe_name_len);
1815 if (ret) {
1816 goto end;
1817 }
1818 ret = lttng_dynamic_buffer_append(buffer,
1819 probe_tracepoint->provider_name, provider_name_len);
1820 if (ret) {
1821 goto end;
1822 }
1823 ret = lttng_dynamic_buffer_append(buffer,
1824 probe_tracepoint->binary_path, binary_path_len);
1825 if (ret) {
1826 goto end;
1827 }
1828
1829 /* Insert padding before the lookup method. */
1830 ret = lttng_dynamic_buffer_set_size(buffer, buffer->size + padding_needed);
1831 if (ret) {
1832 goto end;
1833 }
1834
1835 if (!location->lookup_method) {
1836 /* Not an error, the default method is used. */
1837 ret = storage_needed;
1838 goto end;
1839 }
1840
1841 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
1842
1843 flat_lookup_method.parent.type =
1844 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT;
1845 ret = lttng_dynamic_buffer_append(buffer,
1846 &flat_lookup_method, sizeof(flat_lookup_method));
1847 if (ret) {
1848 goto end;
1849 }
1850 ret = storage_needed;
1851end:
1852 return ret;
1853}
1854
1ce46cfe
JG
1855int lttng_userspace_probe_location_flatten(
1856 const struct lttng_userspace_probe_location *location,
1857 struct lttng_dynamic_buffer *buffer)
1858{
1859 int ret;
1860 if (!location) {
1861 ret = -LTTNG_ERR_INVALID;
1862 goto end;
1863 }
1864
1865 /* Only types currently supported. */
1866 switch (location->type) {
1867 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1868 ret = lttng_userspace_probe_location_function_flatten(location, buffer);
1869 break;
f4d0bb2e
FD
1870 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1871 ret = lttng_userspace_probe_location_tracepoint_flatten(location, buffer);
1872 break;
1ce46cfe
JG
1873 default:
1874 ret = -LTTNG_ERR_INVALID;
1875 goto end;
1876 }
1877
1878end:
1879 return ret;
1880}
394357fe 1881
394357fe
FD
1882struct lttng_userspace_probe_location *lttng_userspace_probe_location_copy(
1883 const struct lttng_userspace_probe_location *location)
1884{
1885 struct lttng_userspace_probe_location *new_location = NULL;
1886 enum lttng_userspace_probe_location_type type;
1887
1888 if (!location) {
1889 goto err;
1890 }
1891
1892 type = lttng_userspace_probe_location_get_type(location);
1893 switch (type) {
1894 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1895 new_location =
1896 lttng_userspace_probe_location_function_copy(location);
1897 if (!new_location) {
1898 goto err;
1899 }
1900 break;
f4d0bb2e
FD
1901 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1902 new_location =
1903 lttng_userspace_probe_location_tracepoint_copy(location);
1904 if (!new_location) {
1905 goto err;
1906 }
1907 break;
394357fe
FD
1908 default:
1909 new_location = NULL;
1910 goto err;
1911 }
1912err:
1913 return new_location;
1914}
dfcfa983 1915
dfcfa983
JR
1916bool lttng_userspace_probe_location_lookup_method_is_equal(
1917 const struct lttng_userspace_probe_location_lookup_method *a,
1918 const struct lttng_userspace_probe_location_lookup_method *b)
1919{
1920 bool is_equal = false;
1921
1922 if (!a || !b) {
1923 goto end;
1924 }
1925
1926 if (a == b) {
1927 is_equal = true;
1928 goto end;
1929 }
1930
1931 if (a->type != b->type) {
1932 goto end;
1933 }
1934
1935 is_equal = true;
1936end:
1937 return is_equal;
1938}
1939
dfcfa983
JR
1940bool lttng_userspace_probe_location_is_equal(
1941 const struct lttng_userspace_probe_location *a,
1942 const struct lttng_userspace_probe_location *b)
1943{
1944 bool is_equal = false;
1945
1946 if (!a || !b) {
1947 goto end;
1948 }
1949
1950 if (a == b) {
1951 is_equal = true;
1952 goto end;
1953 }
1954
1955 if (!lttng_userspace_probe_location_lookup_method_is_equal(
1956 a->lookup_method, b->lookup_method)) {
1957 goto end;
1958 }
1959
1960 if (a->type != b->type) {
1961 goto end;
1962 }
1963
1964 is_equal = a->equal ? a->equal(a, b) : true;
1965end:
1966 return is_equal;
1967}
959e3c66 1968
959e3c66
JR
1969unsigned long lttng_userspace_probe_location_hash(
1970 const struct lttng_userspace_probe_location *location)
1971{
1972 return location->hash(location);
1973}
6a751b95 1974
6a751b95
JR
1975enum lttng_error_code lttng_userspace_probe_location_mi_serialize(
1976 const struct lttng_userspace_probe_location *location,
1977 struct mi_writer *writer)
1978{
1979 typedef enum lttng_error_code (*mi_fp)(
1980 const struct lttng_userspace_probe_location *,
1981 struct mi_writer *);
1982
1983 int ret;
1984 enum lttng_error_code ret_code;
1985 mi_fp mi_function = NULL;
1986
a0377dfe
FD
1987 LTTNG_ASSERT(location);
1988 LTTNG_ASSERT(writer);
6a751b95
JR
1989
1990 switch (lttng_userspace_probe_location_get_type(location)) {
1991 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
1992 mi_function = lttng_userspace_probe_location_function_mi_serialize;
1993 break;
1994 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
1995 mi_function = lttng_userspace_probe_location_tracepoint_mi_serialize;
1996 break;
1997 default:
1998 abort();
1999 break;
2000 }
2001
2002 /* Open userspace probe location element. */
2003 ret = mi_lttng_writer_open_element(
2004 writer, mi_lttng_element_userspace_probe_location);
2005 if (ret) {
2006 goto mi_error;
2007 }
2008
2009 /* Underlying user space probe location. */
2010 ret_code = mi_function(location, writer);
2011 if (ret_code != LTTNG_OK) {
2012 goto end;
2013 }
2014
2015 /* Close userspace probe location element. */
2016 ret = mi_lttng_writer_close_element(writer);
2017 if (ret) {
2018 goto mi_error;
2019 }
2020
2021 ret_code = LTTNG_OK;
2022 goto end;
2023
2024mi_error:
2025 ret_code = LTTNG_ERR_MI_IO_FAIL;
2026end:
2027 return ret_code;
2028}
2029
2030enum lttng_error_code lttng_userspace_probe_location_lookup_method_mi_serialize(
2031 const struct lttng_userspace_probe_location_lookup_method
2032 *method,
2033 struct mi_writer *writer)
2034{
2035 int ret;
2036 enum lttng_error_code ret_code;
2037 const char *type_element_str;
2038
a0377dfe
FD
2039 LTTNG_ASSERT(method);
2040 LTTNG_ASSERT(writer);
6a751b95
JR
2041
2042 switch (lttng_userspace_probe_location_lookup_method_get_type(method)) {
2043 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
2044 type_element_str =
2045 mi_lttng_element_userspace_probe_location_lookup_method_function_default;
2046 break;
2047 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
2048 type_element_str =
2049 mi_lttng_element_userspace_probe_location_lookup_method_function_elf;
2050 break;
2051 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
2052 type_element_str =
2053 mi_lttng_element_userspace_probe_location_lookup_method_tracepoint_sdt;
2054 break;
2055 default:
2056 abort();
2057 break;
2058 }
2059
2060 /* Open userspace probe location lookup method element. */
2061 ret = mi_lttng_writer_open_element(writer,
2062 mi_lttng_element_userspace_probe_location_lookup_method);
2063 if (ret) {
2064 goto mi_error;
2065 }
2066
2067 /* User space probe location lookup method empty element. */
2068 ret = mi_lttng_writer_open_element(writer, type_element_str);
2069 if (ret) {
2070 goto mi_error;
2071 }
2072
2073 /* Close userspace probe location lookup method element. */
2074 ret = mi_lttng_close_multi_element(writer, 2);
2075 if (ret) {
2076 goto mi_error;
2077 }
2078
2079 ret_code = LTTNG_OK;
2080 goto end;
2081
2082mi_error:
2083 ret_code = LTTNG_ERR_MI_IO_FAIL;
2084end:
2085 return ret_code;
2086}
2087
2088static enum lttng_error_code lttng_userspace_probe_location_tracepoint_mi_serialize(
2089 const struct lttng_userspace_probe_location *location,
2090 struct mi_writer *writer)
2091{
2092 int ret;
2093 enum lttng_error_code ret_code;
2094 const char *probe_name = NULL;
2095 const char *provider_name = NULL;
2096 const char *binary_path = NULL;
2097 const struct lttng_userspace_probe_location_lookup_method
2098 *lookup_method = NULL;
2099
a0377dfe
FD
2100 LTTNG_ASSERT(location);
2101 LTTNG_ASSERT(writer);
6a751b95
JR
2102
2103 probe_name = lttng_userspace_probe_location_tracepoint_get_probe_name(
2104 location);
2105 provider_name = lttng_userspace_probe_location_tracepoint_get_provider_name(
2106 location);
2107 binary_path = lttng_userspace_probe_location_tracepoint_get_binary_path(
2108 location);
2109 lookup_method = lttng_userspace_probe_location_tracepoint_get_lookup_method(
2110 location);
2111
2112 /* Open userspace probe location tracepoint element. */
2113 ret = mi_lttng_writer_open_element(writer,
2114 mi_lttng_element_userspace_probe_location_tracepoint);
2115 if (ret) {
2116 goto mi_error;
2117 }
2118
2119 /* Probe name. */
2120 ret = mi_lttng_writer_write_element_string(writer,
2121 mi_lttng_element_userspace_probe_location_tracepoint_probe_name,
2122 probe_name);
2123 if (ret) {
2124 goto mi_error;
2125 }
2126
2127 /* Provider name. */
2128 ret = mi_lttng_writer_write_element_string(writer,
2129 mi_lttng_element_userspace_probe_location_tracepoint_provider_name,
2130 provider_name);
2131 if (ret) {
2132 goto mi_error;
2133 }
2134
2135 /* Binary path. */
2136 ret = mi_lttng_writer_write_element_string(writer,
2137 mi_lttng_element_userspace_probe_location_binary_path,
2138 binary_path);
2139 if (ret) {
2140 goto mi_error;
2141 }
2142
2143 /* The lookup method. */
2144 ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize(
2145 lookup_method, writer);
2146 if (ret_code != LTTNG_OK) {
2147 goto end;
2148 }
2149
2150 /* Close userspace probe location tracepoint. */
2151 ret = mi_lttng_writer_close_element(writer);
2152 if (ret) {
2153 goto mi_error;
2154 }
2155
2156 ret_code = LTTNG_OK;
2157 goto end;
2158
2159mi_error:
2160 ret_code = LTTNG_ERR_MI_IO_FAIL;
2161end:
2162 return ret_code;
2163}
2164
2165static enum lttng_error_code lttng_userspace_probe_location_function_mi_serialize(
2166 const struct lttng_userspace_probe_location *location,
2167 struct mi_writer *writer)
2168{
2169 int ret;
2170 enum lttng_error_code ret_code;
2171 const char *function_name = NULL;
2172 const char *binary_path = NULL;
2173 const char *instrumentation_type_str = NULL;
2174 enum lttng_userspace_probe_location_function_instrumentation_type
2175 instrumentation_type;
2176 const struct lttng_userspace_probe_location_lookup_method
2177 *lookup_method = NULL;
2178
a0377dfe
FD
2179 LTTNG_ASSERT(location);
2180 LTTNG_ASSERT(writer);
6a751b95
JR
2181
2182 function_name = lttng_userspace_probe_location_function_get_function_name(
2183 location);
2184 binary_path = lttng_userspace_probe_location_function_get_binary_path(
2185 location);
2186 instrumentation_type =
2187 lttng_userspace_probe_location_function_get_instrumentation_type(
2188 location);
2189 lookup_method = lttng_userspace_probe_location_function_get_lookup_method(
2190 location);
2191
2192 switch (instrumentation_type) {
2193 case LTTNG_USERSPACE_PROBE_LOCATION_FUNCTION_INSTRUMENTATION_TYPE_ENTRY:
2194 instrumentation_type_str =
2195 mi_lttng_userspace_probe_location_function_instrumentation_type_entry;
2196 break;
2197 default:
2198 abort();
2199 break;
2200 }
2201
2202 /* Open userspace probe location function element. */
2203 ret = mi_lttng_writer_open_element(writer,
2204 mi_lttng_element_userspace_probe_location_function);
2205 if (ret) {
2206 goto mi_error;
2207 }
2208
2209 /* Function name. */
2210 ret = mi_lttng_writer_write_element_string(writer,
2211 mi_lttng_element_userspace_probe_location_function_name,
2212 function_name);
2213 if (ret) {
2214 goto mi_error;
2215 }
2216
2217 /* Binary path. */
2218 ret = mi_lttng_writer_write_element_string(writer,
2219 mi_lttng_element_userspace_probe_location_binary_path,
2220 binary_path);
2221 if (ret) {
2222 goto mi_error;
2223 }
2224
2225 /* Instrumentation type. */
2226 ret = mi_lttng_writer_write_element_string(writer,
2227 mi_lttng_element_userspace_probe_location_function_instrumentation_type,
2228 instrumentation_type_str);
2229 if (ret) {
2230 goto mi_error;
2231 }
2232
2233 /* The lookup method. */
2234 ret_code = lttng_userspace_probe_location_lookup_method_mi_serialize(
2235 lookup_method, writer);
2236 if (ret_code != LTTNG_OK) {
2237 goto end;
2238 }
2239
2240 /* Close userspace probe location function element. */
2241 ret = mi_lttng_writer_close_element(writer);
2242 if (ret) {
2243 goto mi_error;
2244 }
2245
2246 ret_code = LTTNG_OK;
2247 goto end;
2248
2249mi_error:
2250 ret_code = LTTNG_ERR_MI_IO_FAIL;
2251end:
2252 return ret_code;
2253}
This page took 0.147213 seconds and 4 git commands to generate.