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