Cleanup: move session saving of K(ret)probe and function tracing to dedicated functions
[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
56f0bc67
JG
418 memset(&location_generic_comm, 0, sizeof(location_generic_comm));
419
1ce46cfe
JG
420 location_generic_comm.type = (int8_t) location->type;
421 if (buffer) {
422 ret = lttng_dynamic_buffer_append(buffer, &location_generic_comm,
423 sizeof(location_generic_comm));
424 if (ret) {
425 goto end;
426 }
427 }
428 buffer_use += sizeof(location_generic_comm);
429
430 switch (lttng_userspace_probe_location_get_type(location)) {
431 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
432 ret = lttng_userspace_probe_location_function_serialize(
433 location, buffer, binary_fd);
434 break;
435 default:
436 ERR("Unsupported probe location type");
437 ret = -LTTNG_ERR_INVALID;
438 goto end;
439 }
440 if (ret < 0) {
441 goto end;
442 }
443 buffer_use += ret;
444
445 ret = lttng_userspace_probe_location_lookup_method_serialize(
446 location->lookup_method, buffer);
447 if (ret < 0) {
448 goto end;
449 }
450 ret += buffer_use;
451end:
452 return ret;
453}
454
455static
456int lttng_userspace_probe_location_function_create_from_buffer(
457 const struct lttng_buffer_view *buffer,
458 struct lttng_userspace_probe_location **location)
459{
460 struct lttng_userspace_probe_location_function_comm *location_function_comm;
461 const char *function_name_src, *binary_path_src;
462 char *function_name = NULL, *binary_path = NULL;
463 int ret = 0;
464
465 assert(buffer);
466 assert(buffer->data);
467 assert(location);
468
469 location_function_comm =
470 (struct lttng_userspace_probe_location_function_comm *) buffer->data;
471
472 const size_t expected_size = sizeof(*location_function_comm) +
473 location_function_comm->function_name_len +
474 location_function_comm->binary_path_len;
475
476 if (buffer->size < expected_size) {
477 ret = -LTTNG_ERR_INVALID;
478 goto end;
479 }
480
481 function_name_src = buffer->data + sizeof(*location_function_comm);
482 binary_path_src = function_name_src +
483 location_function_comm->function_name_len;
484
485 if (function_name_src[location_function_comm->function_name_len - 1] != '\0') {
486 ret = -LTTNG_ERR_INVALID;
487 goto end;
488 }
489 if (binary_path_src[location_function_comm->binary_path_len - 1] != '\0') {
490 ret = -LTTNG_ERR_INVALID;
491 goto end;
492 }
493
494 function_name = lttng_strndup(function_name_src, LTTNG_SYMBOL_NAME_LEN);
495 if (!function_name) {
496 PERROR("lttng_strndup");
497 goto end;
498 }
499
500 binary_path = lttng_strndup(binary_path_src, LTTNG_PATH_MAX);
501 if (!binary_path) {
502 PERROR("lttng_strndup");
503 goto end;
504 }
505
506 *location = lttng_userspace_probe_location_function_create_no_check(
507 binary_path, function_name, NULL, false);
508 if (!(*location)) {
509 ret = -LTTNG_ERR_INVALID;
510 goto end;
511 }
512
513 ret = (int) expected_size;
514end:
515 free(function_name);
516 free(binary_path);
517 return ret;
518}
519
520static
521int lttng_userspace_probe_location_lookup_method_create_from_buffer(
522 struct lttng_buffer_view *buffer,
523 struct lttng_userspace_probe_location_lookup_method **lookup_method)
524{
525 int ret;
526 struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
527 enum lttng_userspace_probe_location_lookup_method_type type;
528
529 assert(buffer);
530 assert(buffer->data);
531 assert(lookup_method);
532
533 if (buffer->size < sizeof(*lookup_comm)) {
534 ret = -LTTNG_ERR_INVALID;
535 goto end;
536 }
537
538 lookup_comm = (struct lttng_userspace_probe_location_lookup_method_comm *)
539 buffer->data;
540 type = (enum lttng_userspace_probe_location_lookup_method_type)
541 lookup_comm->type;
542 switch (type) {
543 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT:
544 *lookup_method = NULL;
545 break;
546 case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF:
547 *lookup_method =
548 lttng_userspace_probe_location_lookup_method_function_elf_create();
549 if (!(*lookup_method)) {
550 ret = -LTTNG_ERR_INVALID;
551 goto end;
552 }
553 break;
554 default:
555 ret = -LTTNG_ERR_INVALID;
556 goto end;
557 }
558
559 ret = sizeof(*lookup_comm);
560end:
561 return ret;
562}
563
564LTTNG_HIDDEN
565int lttng_userspace_probe_location_create_from_buffer(
566 const struct lttng_buffer_view *buffer,
567 struct lttng_userspace_probe_location **location)
568{
569 struct lttng_userspace_probe_location_lookup_method *lookup_method;
570 struct lttng_userspace_probe_location_comm *probe_location_comm;
571 enum lttng_userspace_probe_location_type type;
572 struct lttng_buffer_view lookup_method_view;
573 int consumed = 0;
574 int ret;
575
576
577 assert(buffer);
578 assert(buffer->data);
579 assert(location);
580
581 lookup_method = NULL;
582
583 if (buffer->size <= sizeof(*probe_location_comm)) {
584 ret = -LTTNG_ERR_INVALID;
585 goto end;
586 }
587
588 probe_location_comm =
589 (struct lttng_userspace_probe_location_comm *) buffer->data;
590 type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
591 consumed += sizeof(*probe_location_comm);
592
593 switch (type) {
594 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
595 {
596 struct lttng_buffer_view view = lttng_buffer_view_from_view(
597 buffer, consumed, buffer->size - consumed);
598
599 ret = lttng_userspace_probe_location_function_create_from_buffer(
600 &view, location);
601 if (ret < 0) {
602 goto end;
603 }
604 break;
605 }
606 default:
607 ret = -LTTNG_ERR_INVALID;
608 goto end;
609 }
610
611 consumed += ret;
612 if (buffer->size <= consumed) {
613 ret = -LTTNG_ERR_INVALID;
614 goto end;
615 }
616
617 lookup_method_view = lttng_buffer_view_from_view(buffer, consumed,
618 buffer->size - consumed);
619 ret = lttng_userspace_probe_location_lookup_method_create_from_buffer(
620 &lookup_method_view, &lookup_method);
621 if (ret < 0) {
622 ret = -LTTNG_ERR_INVALID;
623 goto end;
624 }
625
626 assert(lookup_method);
627 (*location)->lookup_method = lookup_method;
628 lookup_method = NULL;
629 ret += consumed;
630end:
631 return ret;
632}
633
634LTTNG_HIDDEN
635int lttng_userspace_probe_location_function_set_binary_fd(
636 struct lttng_userspace_probe_location *location, int binary_fd)
637{
638 int ret = 0;
639 struct lttng_userspace_probe_location_function *function_location;
640
641 assert(location);
642 assert(location->type == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION);
643
644 function_location = container_of(location,
645 struct lttng_userspace_probe_location_function, parent);
646 if (function_location->binary_fd >= 0) {
647 ret = close(function_location->binary_fd);
648 if (ret) {
649 PERROR("close");
650 ret = -LTTNG_ERR_INVALID;
651 goto end;
652 }
653 }
654
655 function_location->binary_fd = binary_fd;
656end:
657 return ret;
658}
659
660static
661int lttng_userspace_probe_location_function_flatten(
662 const struct lttng_userspace_probe_location *location,
663 struct lttng_dynamic_buffer *buffer)
664{
665 struct lttng_userspace_probe_location_lookup_method_elf flat_lookup_method;
666 struct lttng_userspace_probe_location_function *probe_function;
667 struct lttng_userspace_probe_location_function flat_probe;
668 size_t function_name_len, binary_path_len;
669 size_t padding_needed = 0;
670 char *flat_probe_start;
671 int storage_needed = 0;
672 int ret;
673
674 assert(location);
675
676 if (location->lookup_method && location->lookup_method->type !=
677 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF) {
678 ret = -LTTNG_ERR_INVALID;
679 goto end;
680 }
681
682 probe_function = container_of(location,
683 struct lttng_userspace_probe_location_function,
684 parent);
685 assert(probe_function->function_name);
686 assert(probe_function->binary_path);
687
688 storage_needed +=
689 sizeof(struct lttng_userspace_probe_location_function);
690 function_name_len = strlen(probe_function->function_name) + 1;
691 binary_path_len = strlen(probe_function->binary_path) + 1;
692 storage_needed += function_name_len + binary_path_len;
693
694 /*
695 * The lookup method is aligned to 64-bit within the buffer.
696 * This is needed even if there is no lookup method since
697 * the next structure in the buffer probably needs to be
698 * aligned too (depending on the arch).
699 */
700 padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed;
701 storage_needed += padding_needed;
702
703 if (location->lookup_method) {
704 /* NOTE: elf look-up method is assumed here. */
705 storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf);
706 }
707
708 if (!buffer) {
709 ret = storage_needed;
710 goto end;
711 }
712
713 if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) {
714 ret = lttng_dynamic_buffer_set_capacity(buffer,
715 buffer->size + storage_needed);
716 if (ret) {
717 goto end;
718 }
719 }
720
721 memset(&flat_probe, 0, sizeof(flat_probe));
722
723 flat_probe_start = buffer->data + buffer->size;
724 flat_probe.parent.type = location->type;
725 /*
726 * The lookup method, if present, is the last element in the flat
727 * representation of the probe.
728 */
729 if (location->lookup_method) {
730 flat_probe.parent.lookup_method =
731 (struct lttng_userspace_probe_location_lookup_method *)
732 (flat_probe_start + sizeof(flat_probe) +
733 function_name_len + binary_path_len + padding_needed);
734 } else {
735 flat_probe.parent.lookup_method = NULL;
736 }
737
738 flat_probe.function_name = flat_probe_start + sizeof(flat_probe);
739 flat_probe.binary_path = flat_probe.function_name + function_name_len;
740 flat_probe.binary_fd = -1;
741 ret = lttng_dynamic_buffer_append(buffer, &flat_probe,
742 sizeof(flat_probe));
743 if (ret) {
744 goto end;
745 }
746
747 ret = lttng_dynamic_buffer_append(buffer,
748 probe_function->function_name, function_name_len);
749 if (ret) {
750 goto end;
751 }
752 ret = lttng_dynamic_buffer_append(buffer,
753 probe_function->binary_path, binary_path_len);
754 if (ret) {
755 goto end;
756 }
757
758 /* Insert padding before the lookup method. */
759 ret = lttng_dynamic_buffer_set_size(buffer,
760 buffer->size + padding_needed);
761 if (ret) {
762 goto end;
763 }
764
765 if (!location->lookup_method) {
766 /* Not an error, the default method is used. */
767 ret = storage_needed;
768 goto end;
769 }
770
771 memset(&flat_lookup_method, 0, sizeof(flat_lookup_method));
772 flat_lookup_method.parent.type =
773 LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF;
774 ret = lttng_dynamic_buffer_append(buffer,
775 &flat_lookup_method, sizeof(flat_lookup_method));
776 if (ret) {
777 goto end;
778 }
779 ret = storage_needed;
780end:
781 return ret;
782}
783
784LTTNG_HIDDEN
785int lttng_userspace_probe_location_flatten(
786 const struct lttng_userspace_probe_location *location,
787 struct lttng_dynamic_buffer *buffer)
788{
789 int ret;
790 if (!location) {
791 ret = -LTTNG_ERR_INVALID;
792 goto end;
793 }
794
795 /* Only types currently supported. */
796 switch (location->type) {
797 case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
798 ret = lttng_userspace_probe_location_function_flatten(location, buffer);
799 break;
800 default:
801 ret = -LTTNG_ERR_INVALID;
802 goto end;
803 }
804
805end:
806 return ret;
807}
This page took 0.051365 seconds and 4 git commands to generate.