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