lttng-ctl: add userspace probe location interface
[lttng-tools.git] / src / common / userspace-probe.c
CommitLineData
1ce46cfe
JG
1/*
2 * Copyright (C) 2017 - Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18#include <assert.h>
19#include <common/error.h>
20#include <common/macros.h>
21#include <common/compat/string.h>
22#include <fcntl.h>
23#include <lttng/constant.h>
24#include <lttng/userspace-probe-internal.h>
25
26enum lttng_userspace_probe_location_lookup_method_type
27lttng_userspace_probe_location_lookup_method_get_type(
28 const struct lttng_userspace_probe_location_lookup_method *lookup_method)
29{
30 return lookup_method ? lookup_method->type :
31 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_UNKNOWN;
32}
33
34void lttng_userspace_probe_location_lookup_method_destroy(
35 struct lttng_userspace_probe_location_lookup_method *lookup_method)
36{
37 if (!lookup_method){
38 return;
39 }
40
41 switch (lookup_method->type) {
42 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
43 {
44 struct lttng_userspace_probe_location_lookup_method_elf *elf_method =
45 container_of(lookup_method,
46 struct lttng_userspace_probe_location_lookup_method_elf, parent);
47 free(elf_method);
48 break;
49 }
50 default:
51 break;
52 }
53}
54
55struct lttng_userspace_probe_location_lookup_method *
56lttng_userspace_probe_location_lookup_method_function_elf_create(void)
57{
58 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
59 struct lttng_userspace_probe_location_lookup_method_elf *elf_method;
60
61 elf_method = zmalloc(sizeof(*elf_method));
62 if (!elf_method) {
63 PERROR("zmalloc");
64 goto end;
65 }
66
67 ret = &elf_method->parent;
68 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
69end:
70 return ret;
71}
72
73enum lttng_userspace_probe_location_type lttng_userspace_probe_location_get_type(
74 const struct lttng_userspace_probe_location *location)
75{
76 return location ? location->type :
77 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN;
78}
79
80static
81void lttng_userspace_probe_location_function_destroy(
82 struct lttng_userspace_probe_location *location)
83{
84 struct lttng_userspace_probe_location_function *location_function = NULL;
85
86 assert(location);
87
88 location_function = container_of(location,
89 struct lttng_userspace_probe_location_function, parent);
90
91 assert(location_function);
92
93 free(location_function->function_name);
94 free(location_function->binary_path);
95 if (location_function->binary_fd >= 0) {
96 if (close(location_function->binary_fd)) {
97 PERROR("close");
98 }
99 }
100 free(location);
101}
102
103void lttng_userspace_probe_location_destroy(
104 struct lttng_userspace_probe_location *location)
105{
106 if (!location) {
107 return;
108 }
109
110 lttng_userspace_probe_location_lookup_method_destroy(
111 location->lookup_method);
112
113 switch (location->type) {
114 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
115 lttng_userspace_probe_location_function_destroy(location);
116 break;
117 default:
118 free(location);
119 }
120}
121
122static struct lttng_userspace_probe_location *
123lttng_userspace_probe_location_function_create_no_check(const char *binary_path,
124 const char *function_name,
125 struct lttng_userspace_probe_location_lookup_method *lookup_method,
126 bool open_binary)
127{
128 int binary_fd = -1;
129 char *function_name_copy = NULL, *binary_path_copy = NULL;
130 struct lttng_userspace_probe_location *ret = NULL;
131 struct lttng_userspace_probe_location_function *location;
132
133 if (open_binary) {
134 binary_fd = open(binary_path, O_RDONLY);
135 if (binary_fd < 0) {
136 PERROR("Error opening the binary");
137 goto error;
138 }
139 } else {
140 binary_fd = -1;
141 }
142
143 function_name_copy = lttng_strndup(function_name, LTTNG_SYMBOL_NAME_LEN);
144 if (!function_name_copy) {
145 PERROR("Error duplicating the function name");
146 goto error;
147 }
148
149 binary_path_copy = lttng_strndup(binary_path, LTTNG_PATH_MAX);
150 if (!binary_path_copy) {
151 PERROR("Error duplicating the function name");
152 goto error;
153 }
154
155 location = zmalloc(sizeof(*location));
156 if (!location) {
157 PERROR("Error allocating userspace probe location");
158 goto error;
159 }
160
161 location->function_name = function_name_copy;
162 location->binary_path = binary_path_copy;
163 location->binary_fd = binary_fd;
164
165 ret = &location->parent;
166 ret->lookup_method = lookup_method;
167 ret->type = LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION;
168 goto end;
169
170error:
171 free(function_name_copy);
172 free(binary_path_copy);
173 if (binary_fd >= 0) {
174 if (close(binary_fd)) {
175 PERROR("Error closing binary fd in error path");
176 }
177 }
178end:
179 return ret;
180}
181
182struct lttng_userspace_probe_location *
183lttng_userspace_probe_location_function_create(const char *binary_path,
184 const char *function_name,
185 struct lttng_userspace_probe_location_lookup_method *lookup_method)
186{
187 struct lttng_userspace_probe_location *ret = NULL;
188
189 if (!binary_path || !function_name) {
190 ERR("Invalid argument(s)");
191 goto end;
192 }
193
194 switch (lttng_userspace_probe_location_lookup_method_get_type(
195 lookup_method)) {
196 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
197 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
198 break;
199 default:
200 /* Invalid probe location lookup method. */
201 goto end;
202 }
203
204 ret = lttng_userspace_probe_location_function_create_no_check(
205 binary_path, function_name, lookup_method, true);
206end:
207 return ret;
208}
209
210const char *lttng_userspace_probe_location_function_get_binary_path(
211 const struct lttng_userspace_probe_location *location)
212{
213 const char *ret = NULL;
214 struct lttng_userspace_probe_location_function *function_location;
215
216 if (!location || lttng_userspace_probe_location_get_type(location) !=
217 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
218 ERR("Invalid argument(s)");
219 goto end;
220 }
221
222 function_location = container_of(location,
223 struct lttng_userspace_probe_location_function,
224 parent);
225 ret = function_location->binary_path;
226end:
227 return ret;
228}
229
230const char *lttng_userspace_probe_location_function_get_function_name(
231 const struct lttng_userspace_probe_location *location)
232{
233 const char *ret = NULL;
234 struct lttng_userspace_probe_location_function *function_location;
235
236 if (!location || lttng_userspace_probe_location_get_type(location) !=
237 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
238 ERR("Invalid argument(s)");
239 goto end;
240 }
241
242 function_location = container_of(location,
243 struct lttng_userspace_probe_location_function, parent);
244 ret = function_location->function_name;
245end:
246 return ret;
247}
248
249int lttng_userspace_probe_location_function_get_binary_fd(
250 const struct lttng_userspace_probe_location *location)
251{
252 int ret = -1;
253 struct lttng_userspace_probe_location_function *function_location;
254
255 if (!location || lttng_userspace_probe_location_get_type(location) !=
256 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
257 ERR("Invalid argument(s)");
258 goto end;
259 }
260
261 function_location = container_of(location,
262 struct lttng_userspace_probe_location_function, parent);
263 ret = function_location->binary_fd;
264end:
265 return ret;
266}
267
268static struct lttng_userspace_probe_location_lookup_method *
269lttng_userspace_probe_location_function_get_lookup_method(
270 const struct lttng_userspace_probe_location *location)
271{
272 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
273
274 if (!location || lttng_userspace_probe_location_get_type(location) !=
275 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION) {
276 ERR("Invalid argument(s)");
277 goto end;
278 }
279
280 ret = location->lookup_method;
281end:
282 return ret;
283}
284
285struct lttng_userspace_probe_location_lookup_method *
286lttng_userspace_probe_location_get_lookup_method(
287 const struct lttng_userspace_probe_location *location)
288{
289 struct lttng_userspace_probe_location_lookup_method *ret = NULL;
290
291 assert(location);
292 switch (location->type) {
293 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
294 ret = lttng_userspace_probe_location_function_get_lookup_method(
295 location);
296 break;
297 default:
298 ERR("Unknowned lookup method.");
299 break;
300 }
301 return ret;
302}
303
304static
305int lttng_userspace_probe_location_lookup_method_serialize(
306 struct lttng_userspace_probe_location_lookup_method *method,
307 struct lttng_dynamic_buffer *buffer)
308{
309 int ret;
310 struct lttng_userspace_probe_location_lookup_method_comm
311 lookup_method_comm;
312
313 lookup_method_comm.type = (int8_t) (method ? method->type :
314 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT);
315 if (buffer) {
316 ret = lttng_dynamic_buffer_append(buffer, &lookup_method_comm,
317 sizeof(lookup_method_comm));
318 if (ret) {
319 goto end;
320 }
321 }
322 ret = sizeof(lookup_method_comm);
323end:
324 return ret;
325}
326
327static
328int lttng_userspace_probe_location_function_serialize(
329 const struct lttng_userspace_probe_location *location,
330 struct lttng_dynamic_buffer *buffer,
331 int *binary_fd)
332{
333 int ret;
334 size_t function_name_len, binary_path_len;
335 struct lttng_userspace_probe_location_function *location_function;
336 struct lttng_userspace_probe_location_function_comm location_function_comm;
337
338 assert(location);
339 assert(lttng_userspace_probe_location_get_type(location) ==
340 LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
341
342 location_function = container_of(location,
343 struct lttng_userspace_probe_location_function,
344 parent);
345 if (!location_function->function_name || !location_function->binary_path) {
346 ret = -LTTNG_ERR_INVALID;
347 goto end;
348 }
349
350 if (binary_fd && location_function->binary_fd < 0) {
351 ret = -LTTNG_ERR_INVALID;
352 goto end;
353 }
354
355 if (binary_fd) {
356 *binary_fd = location_function->binary_fd;
357 }
358
359 function_name_len = strlen(location_function->function_name);
360 if (function_name_len == 0) {
361 ret = -LTTNG_ERR_INVALID;
362 goto end;
363 }
364 binary_path_len = strlen(location_function->binary_path);
365 if (binary_path_len == 0) {
366 ret = -LTTNG_ERR_INVALID;
367 goto end;
368 }
369
370 location_function_comm.function_name_len = function_name_len + 1;
371 location_function_comm.binary_path_len = binary_path_len + 1;
372
373 if (buffer) {
374 ret = lttng_dynamic_buffer_append(buffer,
375 &location_function_comm,
376 sizeof(location_function_comm));
377 if (ret) {
378 ret = -LTTNG_ERR_INVALID;
379 goto end;
380 }
381 ret = lttng_dynamic_buffer_append(buffer,
382 location_function->function_name,
383 location_function_comm.function_name_len);
384 if (ret) {
385 ret = -LTTNG_ERR_INVALID;
386 goto end;
387 }
388 ret = lttng_dynamic_buffer_append(buffer,
389 location_function->binary_path,
390 location_function_comm.binary_path_len);
391 if (ret) {
392 ret = -LTTNG_ERR_INVALID;
393 goto end;
394 }
395 }
396 ret = sizeof(location_function_comm) +
397 location_function_comm.function_name_len +
398 location_function_comm.binary_path_len;
399end:
400 return ret;
401}
402
403LTTNG_HIDDEN
404int lttng_userspace_probe_location_serialize(
405 const struct lttng_userspace_probe_location *location,
406 struct lttng_dynamic_buffer *buffer,
407 int *binary_fd)
408{
409 int ret, buffer_use = 0;
410 struct lttng_userspace_probe_location_comm location_generic_comm;
411
412 if (!location) {
413 ERR("Invalid argument(s)");
414 ret = -LTTNG_ERR_INVALID;
415 goto end;
416 }
417
418 location_generic_comm.type = (int8_t) location->type;
419 if (buffer) {
420 ret = lttng_dynamic_buffer_append(buffer, &location_generic_comm,
421 sizeof(location_generic_comm));
422 if (ret) {
423 goto end;
424 }
425 }
426 buffer_use += sizeof(location_generic_comm);
427
428 switch (lttng_userspace_probe_location_get_type(location)) {
429 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
430 ret = lttng_userspace_probe_location_function_serialize(
431 location, buffer, binary_fd);
432 break;
433 default:
434 ERR("Unsupported probe location type");
435 ret = -LTTNG_ERR_INVALID;
436 goto end;
437 }
438 if (ret < 0) {
439 goto end;
440 }
441 buffer_use += ret;
442
443 ret = lttng_userspace_probe_location_lookup_method_serialize(
444 location->lookup_method, buffer);
445 if (ret < 0) {
446 goto end;
447 }
448 ret += buffer_use;
449end:
450 return ret;
451}
452
453static
454int lttng_userspace_probe_location_function_create_from_buffer(
455 const struct lttng_buffer_view *buffer,
456 struct lttng_userspace_probe_location **location)
457{
458 struct lttng_userspace_probe_location_function_comm *location_function_comm;
459 const char *function_name_src, *binary_path_src;
460 char *function_name = NULL, *binary_path = NULL;
461 int ret = 0;
462
463 assert(buffer);
464 assert(buffer->data);
465 assert(location);
466
467 location_function_comm =
468 (struct lttng_userspace_probe_location_function_comm *) buffer->data;
469
470 const size_t expected_size = sizeof(*location_function_comm) +
471 location_function_comm->function_name_len +
472 location_function_comm->binary_path_len;
473
474 if (buffer->size < expected_size) {
475 ret = -LTTNG_ERR_INVALID;
476 goto end;
477 }
478
479 function_name_src = buffer->data + sizeof(*location_function_comm);
480 binary_path_src = function_name_src +
481 location_function_comm->function_name_len;
482
483 if (function_name_src[location_function_comm->function_name_len - 1] != '\0') {
484 ret = -LTTNG_ERR_INVALID;
485 goto end;
486 }
487 if (binary_path_src[location_function_comm->binary_path_len - 1] != '\0') {
488 ret = -LTTNG_ERR_INVALID;
489 goto end;
490 }
491
492 function_name = lttng_strndup(function_name_src, LTTNG_SYMBOL_NAME_LEN);
493 if (!function_name) {
494 PERROR("lttng_strndup");
495 goto end;
496 }
497
498 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
499 if (!binary_path) {
500 PERROR("lttng_strndup");
501 goto end;
502 }
503
504 *location = lttng_userspace_probe_location_function_create_no_check(
505 binary_path, function_name, NULL, false);
506 if (!(*location)) {
507 ret = -LTTNG_ERR_INVALID;
508 goto end;
509 }
510
511 ret = (int) expected_size;
512end:
513 free(function_name);
514 free(binary_path);
515 return ret;
516}
517
518static
519int lttng_userspace_probe_location_lookup_method_create_from_buffer(
520 struct lttng_buffer_view *buffer,
521 struct lttng_userspace_probe_location_lookup_method **lookup_method)
522{
523 int ret;
524 struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
525 enum lttng_userspace_probe_location_lookup_method_type type;
526
527 assert(buffer);
528 assert(buffer->data);
529 assert(lookup_method);
530
531 if (buffer->size < sizeof(*lookup_comm)) {
532 ret = -LTTNG_ERR_INVALID;
533 goto end;
534 }
535
536 lookup_comm = (struct lttng_userspace_probe_location_lookup_method_comm *)
537 buffer->data;
538 type = (enum lttng_userspace_probe_location_lookup_method_type)
539 lookup_comm->type;
540 switch (type) {
541 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
542 *lookup_method = NULL;
543 break;
544 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
545 *lookup_method =
546 lttng_userspace_probe_location_lookup_method_function_elf_create();
547 if (!(*lookup_method)) {
548 ret = -LTTNG_ERR_INVALID;
549 goto end;
550 }
551 break;
552 default:
553 ret = -LTTNG_ERR_INVALID;
554 goto end;
555 }
556
557 ret = sizeof(*lookup_comm);
558end:
559 return ret;
560}
561
562LTTNG_HIDDEN
563int lttng_userspace_probe_location_create_from_buffer(
564 const struct lttng_buffer_view *buffer,
565 struct lttng_userspace_probe_location **location)
566{
567 struct lttng_userspace_probe_location_lookup_method *lookup_method;
568 struct lttng_userspace_probe_location_comm *probe_location_comm;
569 enum lttng_userspace_probe_location_type type;
570 struct lttng_buffer_view lookup_method_view;
571 int consumed = 0;
572 int ret;
573
574
575 assert(buffer);
576 assert(buffer->data);
577 assert(location);
578
579 lookup_method = NULL;
580
581 if (buffer->size <= sizeof(*probe_location_comm)) {
582 ret = -LTTNG_ERR_INVALID;
583 goto end;
584 }
585
586 probe_location_comm =
587 (struct lttng_userspace_probe_location_comm *) buffer->data;
588 type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
589 consumed += sizeof(*probe_location_comm);
590
591 switch (type) {
592 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
593 {
594 struct lttng_buffer_view view = lttng_buffer_view_from_view(
595 buffer, consumed, buffer->size - consumed);
596
597 ret = lttng_userspace_probe_location_function_create_from_buffer(
598 &view, location);
599 if (ret < 0) {
600 goto end;
601 }
602 break;
603 }
604 default:
605 ret = -LTTNG_ERR_INVALID;
606 goto end;
607 }
608
609 consumed += ret;
610 if (buffer->size <= consumed) {
611 ret = -LTTNG_ERR_INVALID;
612 goto end;
613 }
614
615 lookup_method_view = lttng_buffer_view_from_view(buffer, consumed,
616 buffer->size - consumed);
617 ret = lttng_userspace_probe_location_lookup_method_create_from_buffer(
618 &lookup_method_view, &lookup_method);
619 if (ret < 0) {
620 ret = -LTTNG_ERR_INVALID;
621 goto end;
622 }
623
624 assert(lookup_method);
625 (*location)->lookup_method = lookup_method;
626 lookup_method = NULL;
627 ret += consumed;
628end:
629 return ret;
630}
631
632LTTNG_HIDDEN
633int lttng_userspace_probe_location_function_set_binary_fd(
634 struct lttng_userspace_probe_location *location, int binary_fd)
635{
636 int ret = 0;
637 struct lttng_userspace_probe_location_function *function_location;
638
639 assert(location);
640 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
641
642 function_location = container_of(location,
643 struct lttng_userspace_probe_location_function, parent);
644 if (function_location->binary_fd >= 0) {
645 ret = close(function_location->binary_fd);
646 if (ret) {
647 PERROR("close");
648 ret = -LTTNG_ERR_INVALID;
649 goto end;
650 }
651 }
652
653 function_location->binary_fd = binary_fd;
654end:
655 return ret;
656}
657
658static
659int lttng_userspace_probe_location_function_flatten(
660 const struct lttng_userspace_probe_location *location,
661 struct lttng_dynamic_buffer *buffer)
662{
663 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method;
664 struct lttng_userspace_probe_location_function *probe_function;
665 struct lttng_userspace_probe_location_function flat_probe;
666 size_t function_name_len, binary_path_len;
667 size_t padding_needed = 0;
668 char *flat_probe_start;
669 int storage_needed = 0;
670 int ret;
671
672 assert(location);
673
674 if (location->lookup_method && location->lookup_method->type !=
675 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF) {
676 ret = -LTTNG_ERR_INVALID;
677 goto end;
678 }
679
680 probe_function = container_of(location,
681 struct lttng_userspace_probe_location_function,
682 parent);
683 assert(probe_function->function_name);
684 assert(probe_function->binary_path);
685
686 storage_needed +=
687 sizeof(struct lttng_userspace_probe_location_function);
688 function_name_len = strlen(probe_function->function_name) + 1;
689 binary_path_len = strlen(probe_function->binary_path) + 1;
690 storage_needed += function_name_len + binary_path_len;
691
692 /*
693 * The lookup method is aligned to 64-bit within the buffer.
694 * This is needed even if there is no lookup method since
695 * the next structure in the buffer probably needs to be
696 * aligned too (depending on the arch).
697 */
698 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
699 storage_needed += padding_needed;
700
701 if (location->lookup_method) {
702 /* NOTE: elf look-up method is assumed here. */
703 storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
704 }
705
706 if (!buffer) {
707 ret = storage_needed;
708 goto end;
709 }
710
711 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
712 ret = lttng_dynamic_buffer_set_capacity(buffer,
713 buffer->size + storage_needed);
714 if (ret) {
715 goto end;
716 }
717 }
718
719 memset(&flat_probe, 0, sizeof(flat_probe));
720
721 flat_probe_start = buffer->data + buffer->size;
722 flat_probe.parent.type = location->type;
723 /*
724 * The lookup method, if present, is the last element in the flat
725 * representation of the probe.
726 */
727 if (location->lookup_method) {
728 flat_probe.parent.lookup_method =
729 (struct lttng_userspace_probe_location_lookup_method *)
730 (flat_probe_start + sizeof(flat_probe) +
731 function_name_len + binary_path_len + padding_needed);
732 } else {
733 flat_probe.parent.lookup_method = NULL;
734 }
735
736 flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
737 flat_probe.binary_path = flat_probe.function_name + function_name_len;
738 flat_probe.binary_fd = -1;
739 ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
740 sizeof(flat_probe));
741 if (ret) {
742 goto end;
743 }
744
745 ret = lttng_dynamic_buffer_append(buffer,
746 probe_function->function_name, function_name_len);
747 if (ret) {
748 goto end;
749 }
750 ret = lttng_dynamic_buffer_append(buffer,
751 probe_function->binary_path, binary_path_len);
752 if (ret) {
753 goto end;
754 }
755
756 /* Insert padding before the lookup method. */
757 ret = lttng_dynamic_buffer_set_size(buffer,
758 buffer->size + padding_needed);
759 if (ret) {
760 goto end;
761 }
762
763 if (!location->lookup_method) {
764 /* Not an error, the default method is used. */
765 ret = storage_needed;
766 goto end;
767 }
768
769 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
770 flat_lookup_method.parent.type =
771 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
772 ret = lttng_dynamic_buffer_append(buffer,
773 &flat_lookup_method, sizeof(flat_lookup_method));
774 if (ret) {
775 goto end;
776 }
777 ret = storage_needed;
778end:
779 return ret;
780}
781
782LTTNG_HIDDEN
783int lttng_userspace_probe_location_flatten(
784 const struct lttng_userspace_probe_location *location,
785 struct lttng_dynamic_buffer *buffer)
786{
787 int ret;
788 if (!location) {
789 ret = -LTTNG_ERR_INVALID;
790 goto end;
791 }
792
793 /* Only types currently supported. */
794 switch (location->type) {
795 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
796 ret = lttng_userspace_probe_location_function_flatten(location, buffer);
797 break;
798 default:
799 ret = -LTTNG_ERR_INVALID;
800 goto end;
801 }
802
803end:
804 return ret;
805}
This page took 0.054309 seconds and 5 git commands to generate.