2 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
3 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #define BT_LOG_TAG "LIB/PLUGIN-SO"
27 #include "lib/logging.h"
29 #include "common/assert.h"
30 #include "lib/assert-pre.h"
31 #include "compat/compiler.h"
32 #include <babeltrace2/plugin/plugin-dev.h>
33 #include "lib/graph/component-class.h"
34 #include <babeltrace2/graph/component-class.h>
35 #include <babeltrace2/graph/component-class-source.h>
36 #include <babeltrace2/graph/component-class-filter.h>
37 #include <babeltrace2/graph/component-class-sink.h>
38 #include <babeltrace2/types.h>
39 #include "common/list.h"
46 #include "plugin-so.h"
47 #include "lib/func-status.h"
48 #include "common/common.h"
50 #define NATIVE_PLUGIN_SUFFIX "." G_MODULE_SUFFIX
51 #define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
52 #define LIBTOOL_PLUGIN_SUFFIX ".la"
53 #define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
55 #define PLUGIN_SUFFIX_LEN bt_max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
56 sizeof(LIBTOOL_PLUGIN_SUFFIX))
61 * This list, global to the library, keeps all component classes that
62 * have a reference to their shared library handles. It allows iteration
63 * on all component classes still present when the destructor executes
64 * to release the shared library handle references they might still have.
66 * The list items are the component classes created with
67 * bt_plugin_add_component_class(). They keep the shared library handle
68 * object created by their plugin alive so that the plugin's code is
69 * not discarded when it could still be in use by living components
70 * created from those component classes:
72 * [component] --ref-> [component class]-> [shlib handle]
74 * It allows this use-case:
76 * my_plugins = bt_plugin_find_all_from_file("/path/to/my-plugin.so");
77 * // instantiate components from a plugin's component classes
78 * // put plugins and free my_plugins here
79 * // user code of instantiated components still exists
81 * An entry is removed from this list when a component class is
82 * destroyed thanks to a custom destroy listener. When the entry is
83 * removed, the entry is removed from the list, and we release the
84 * reference on the shlib handle. Assuming the original plugin object
85 * which contained some component classes is put first, when the last
86 * component class is removed from this list, the shared library handle
87 * object's reference count falls to zero and the shared library is
92 BT_LIST_HEAD(component_class_list
);
94 __attribute__((destructor
)) static
95 void fini_comp_class_list(void)
97 struct bt_component_class
*comp_class
, *tmp
;
99 bt_list_for_each_entry_safe(comp_class
, tmp
, &component_class_list
, node
) {
100 bt_list_del(&comp_class
->node
);
101 BT_OBJECT_PUT_REF_AND_RESET(comp_class
->so_handle
);
104 BT_LOGD_STR("Released references from all component classes to shared library handles.");
108 void bt_plugin_so_shared_lib_handle_destroy(struct bt_object
*obj
)
110 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
;
113 shared_lib_handle
= container_of(obj
,
114 struct bt_plugin_so_shared_lib_handle
, base
);
115 const char *path
= shared_lib_handle
->path
?
116 shared_lib_handle
->path
->str
: NULL
;
118 BT_LOGI("Destroying shared library handle: addr=%p, path=\"%s\"",
119 shared_lib_handle
, path
);
121 if (shared_lib_handle
->init_called
&& shared_lib_handle
->exit
) {
122 BT_LOGD_STR("Calling user's plugin exit function.");
123 shared_lib_handle
->exit();
124 BT_LOGD_STR("User function returned.");
127 if (shared_lib_handle
->module
) {
130 * Valgrind shows incomplete stack traces when
131 * dynamically loaded libraries are closed before it
132 * finishes. Use the LIBBABELTRACE2_NO_DLCLOSE in a debug
133 * build to avoid this.
135 const char *var
= getenv("LIBBABELTRACE2_NO_DLCLOSE");
137 if (!var
|| strcmp(var
, "1") != 0) {
139 BT_LOGI("Closing GModule: path=\"%s\"", path
);
141 if (!g_module_close(shared_lib_handle
->module
)) {
143 * Just log here: we're in a destructor,
144 * so we cannot append an error cause
145 * (there's no returned status).
147 BT_LOGE("Cannot close GModule: %s: path=\"%s\"",
148 g_module_error(), path
);
151 shared_lib_handle
->module
= NULL
;
154 BT_LOGI("Not closing GModule because `LIBBABELTRACE2_NO_DLCLOSE=1`: "
155 "path=\"%s\"", path
);
160 if (shared_lib_handle
->path
) {
161 g_string_free(shared_lib_handle
->path
, TRUE
);
162 shared_lib_handle
->path
= NULL
;
165 g_free(shared_lib_handle
);
169 int bt_plugin_so_shared_lib_handle_create(
171 struct bt_plugin_so_shared_lib_handle
**shared_lib_handle
)
173 int status
= BT_FUNC_STATUS_OK
;
175 BT_ASSERT(shared_lib_handle
);
176 BT_LOGI("Creating shared library handle: path=\"%s\"", path
);
177 *shared_lib_handle
= g_new0(struct bt_plugin_so_shared_lib_handle
, 1);
178 if (!*shared_lib_handle
) {
179 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one shared library handle.");
180 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
184 bt_object_init_shared(&(*shared_lib_handle
)->base
,
185 bt_plugin_so_shared_lib_handle_destroy
);
191 (*shared_lib_handle
)->path
= g_string_new(path
);
192 if (!(*shared_lib_handle
)->path
) {
193 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
194 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
198 (*shared_lib_handle
)->module
= g_module_open(path
, G_MODULE_BIND_LOCAL
);
199 if (!(*shared_lib_handle
)->module
) {
201 * INFO-level logging because we're only _trying_ to
202 * open this file as a Babeltrace plugin: if it's not,
203 * it's not an error. And because this can be tried
204 * during bt_plugin_find_all_from_dir(), it's not even a
207 BT_LOGI("Cannot open GModule: %s: path=\"%s\"",
208 g_module_error(), path
);
209 BT_OBJECT_PUT_REF_AND_RESET(*shared_lib_handle
);
210 status
= BT_FUNC_STATUS_NOT_FOUND
;
217 BT_ASSERT(*shared_lib_handle
|| status
!= BT_FUNC_STATUS_OK
);
218 if (*shared_lib_handle
) {
219 BT_LOGI("Created shared library handle: path=\"%s\", addr=%p",
220 path
, *shared_lib_handle
);
227 void bt_plugin_so_destroy_spec_data(struct bt_plugin
*plugin
)
229 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
231 if (!plugin
->spec_data
) {
235 BT_ASSERT(plugin
->type
== BT_PLUGIN_TYPE_SO
);
237 BT_OBJECT_PUT_REF_AND_RESET(spec
->shared_lib_handle
);
238 g_free(plugin
->spec_data
);
239 plugin
->spec_data
= NULL
;
243 * This function does the following:
245 * 1. Iterate on the plugin descriptor attributes section and set the
246 * plugin's attributes depending on the attribute types. This
247 * includes the name of the plugin, its description, and its
248 * initialization function, for example.
250 * 2. Iterate on the component class descriptors section and create one
251 * "full descriptor" (temporary structure) for each one that is found
252 * and attached to our plugin descriptor.
254 * 3. Iterate on the component class descriptor attributes section and
255 * set the corresponding full descriptor's attributes depending on
256 * the attribute types. This includes the description of the
257 * component class, as well as its initialization and destroy
260 * 4. Call the user's plugin initialization function, if any is
263 * 5. For each full component class descriptor, create a component class
264 * object, set its optional attributes, and add it to the plugin
267 * 6. Freeze the plugin object.
270 int bt_plugin_so_init(struct bt_plugin
*plugin
,
271 bool fail_on_load_error
,
272 const struct __bt_plugin_descriptor
*descriptor
,
273 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
274 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
275 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
276 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
277 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
278 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
)
281 * This structure's members point to the plugin's memory
284 struct comp_class_full_descriptor
{
285 const struct __bt_plugin_component_class_descriptor
*descriptor
;
286 const char *description
;
291 bt_component_class_source_init_method init
;
292 bt_component_class_source_finalize_method finalize
;
293 bt_component_class_source_query_method query
;
294 bt_component_class_source_output_port_connected_method output_port_connected
;
295 bt_component_class_source_message_iterator_init_method msg_iter_init
;
296 bt_component_class_source_message_iterator_finalize_method msg_iter_finalize
;
297 bt_component_class_source_message_iterator_seek_ns_from_origin_method msg_iter_seek_ns_from_origin
;
298 bt_component_class_source_message_iterator_seek_beginning_method msg_iter_seek_beginning
;
299 bt_component_class_source_message_iterator_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin
;
300 bt_component_class_source_message_iterator_can_seek_beginning_method msg_iter_can_seek_beginning
;
304 bt_component_class_filter_init_method init
;
305 bt_component_class_filter_finalize_method finalize
;
306 bt_component_class_filter_query_method query
;
307 bt_component_class_filter_input_port_connected_method input_port_connected
;
308 bt_component_class_filter_output_port_connected_method output_port_connected
;
309 bt_component_class_filter_message_iterator_init_method msg_iter_init
;
310 bt_component_class_filter_message_iterator_finalize_method msg_iter_finalize
;
311 bt_component_class_filter_message_iterator_seek_ns_from_origin_method msg_iter_seek_ns_from_origin
;
312 bt_component_class_filter_message_iterator_seek_beginning_method msg_iter_seek_beginning
;
313 bt_component_class_filter_message_iterator_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin
;
314 bt_component_class_filter_message_iterator_can_seek_beginning_method msg_iter_can_seek_beginning
;
318 bt_component_class_sink_init_method init
;
319 bt_component_class_sink_finalize_method finalize
;
320 bt_component_class_sink_query_method query
;
321 bt_component_class_sink_input_port_connected_method input_port_connected
;
322 bt_component_class_sink_graph_is_configured_method graph_is_configured
;
327 int status
= BT_FUNC_STATUS_OK
;
328 struct __bt_plugin_descriptor_attribute
const * const *cur_attr_ptr
;
329 struct __bt_plugin_component_class_descriptor
const * const *cur_cc_descr_ptr
;
330 struct __bt_plugin_component_class_descriptor_attribute
const * const *cur_cc_descr_attr_ptr
;
331 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
332 GArray
*comp_class_full_descriptors
;
336 BT_LOGI("Initializing plugin object from descriptors found in sections: "
337 "plugin-addr=%p, plugin-path=\"%s\", "
338 "attrs-begin-addr=%p, attrs-end-addr=%p, "
339 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
340 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p",
342 spec
->shared_lib_handle
->path
?
343 spec
->shared_lib_handle
->path
->str
: NULL
,
344 attrs_begin
, attrs_end
,
345 cc_descriptors_begin
, cc_descriptors_end
,
346 cc_descr_attrs_begin
, cc_descr_attrs_end
);
347 comp_class_full_descriptors
= g_array_new(FALSE
, TRUE
,
348 sizeof(struct comp_class_full_descriptor
));
349 if (!comp_class_full_descriptors
) {
350 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
351 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
355 /* Set mandatory attributes */
356 spec
->descriptor
= descriptor
;
357 bt_plugin_set_name(plugin
, descriptor
->name
);
360 * Find and set optional attributes attached to this plugin
363 for (cur_attr_ptr
= attrs_begin
; cur_attr_ptr
!= attrs_end
; cur_attr_ptr
++) {
364 const struct __bt_plugin_descriptor_attribute
*cur_attr
=
371 if (cur_attr
->plugin_descriptor
!= descriptor
) {
375 switch (cur_attr
->type
) {
376 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT
:
377 spec
->init
= cur_attr
->value
.init
;
379 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT
:
380 spec
->shared_lib_handle
->exit
= cur_attr
->value
.exit
;
382 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR
:
383 bt_plugin_set_author(plugin
, cur_attr
->value
.author
);
385 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE
:
386 bt_plugin_set_license(plugin
, cur_attr
->value
.license
);
388 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
389 bt_plugin_set_description(plugin
, cur_attr
->value
.description
);
391 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION
:
392 bt_plugin_set_version(plugin
,
393 (unsigned int) cur_attr
->value
.version
.major
,
394 (unsigned int) cur_attr
->value
.version
.minor
,
395 (unsigned int) cur_attr
->value
.version
.patch
,
396 cur_attr
->value
.version
.extra
);
399 if (fail_on_load_error
) {
400 BT_LIB_LOGW_APPEND_CAUSE(
401 "Unknown plugin descriptor attribute: "
402 "plugin-path=\"%s\", plugin-name=\"%s\", "
403 "attr-type-name=\"%s\", attr-type-id=%d",
404 spec
->shared_lib_handle
->path
?
405 spec
->shared_lib_handle
->path
->str
:
407 descriptor
->name
, cur_attr
->type_name
,
409 status
= BT_FUNC_STATUS_ERROR
;
413 "Ignoring unknown plugin descriptor attribute: "
414 "plugin-path=\"%s\", plugin-name=\"%s\", "
415 "attr-type-name=\"%s\", attr-type-id=%d",
416 spec
->shared_lib_handle
->path
?
417 spec
->shared_lib_handle
->path
->str
:
419 descriptor
->name
, cur_attr
->type_name
,
428 * Find component class descriptors attached to this plugin
429 * descriptor and initialize corresponding full component class
430 * descriptors in the array.
432 for (cur_cc_descr_ptr
= cc_descriptors_begin
; cur_cc_descr_ptr
!= cc_descriptors_end
; cur_cc_descr_ptr
++) {
433 const struct __bt_plugin_component_class_descriptor
*cur_cc_descr
=
435 struct comp_class_full_descriptor full_descriptor
= {0};
441 if (cur_cc_descr
->plugin_descriptor
!= descriptor
) {
445 full_descriptor
.descriptor
= cur_cc_descr
;
446 g_array_append_val(comp_class_full_descriptors
,
451 * Find component class descriptor attributes attached to this
452 * plugin descriptor and update corresponding full component
453 * class descriptors in the array.
455 for (cur_cc_descr_attr_ptr
= cc_descr_attrs_begin
; cur_cc_descr_attr_ptr
!= cc_descr_attrs_end
; cur_cc_descr_attr_ptr
++) {
456 const struct __bt_plugin_component_class_descriptor_attribute
*cur_cc_descr_attr
=
457 *cur_cc_descr_attr_ptr
;
458 enum bt_component_class_type cc_type
;
460 if (!cur_cc_descr_attr
) {
464 if (cur_cc_descr_attr
->comp_class_descriptor
->plugin_descriptor
!=
469 cc_type
= cur_cc_descr_attr
->comp_class_descriptor
->type
;
471 /* Find the corresponding component class descriptor entry */
472 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
473 struct comp_class_full_descriptor
*cc_full_descr
=
474 &g_array_index(comp_class_full_descriptors
,
475 struct comp_class_full_descriptor
, i
);
477 if (cur_cc_descr_attr
->comp_class_descriptor
!=
478 cc_full_descr
->descriptor
) {
482 switch (cur_cc_descr_attr
->type
) {
483 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
484 cc_full_descr
->description
=
485 cur_cc_descr_attr
->value
.description
;
487 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP
:
488 cc_full_descr
->help
=
489 cur_cc_descr_attr
->value
.help
;
491 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INIT_METHOD
:
493 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
494 cc_full_descr
->methods
.source
.init
=
495 cur_cc_descr_attr
->value
.source_init_method
;
497 case BT_COMPONENT_CLASS_TYPE_FILTER
:
498 cc_full_descr
->methods
.filter
.init
=
499 cur_cc_descr_attr
->value
.filter_init_method
;
501 case BT_COMPONENT_CLASS_TYPE_SINK
:
502 cc_full_descr
->methods
.sink
.init
=
503 cur_cc_descr_attr
->value
.sink_init_method
;
509 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD
:
511 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
512 cc_full_descr
->methods
.source
.finalize
=
513 cur_cc_descr_attr
->value
.source_finalize_method
;
515 case BT_COMPONENT_CLASS_TYPE_FILTER
:
516 cc_full_descr
->methods
.filter
.finalize
=
517 cur_cc_descr_attr
->value
.filter_finalize_method
;
519 case BT_COMPONENT_CLASS_TYPE_SINK
:
520 cc_full_descr
->methods
.sink
.finalize
=
521 cur_cc_descr_attr
->value
.sink_finalize_method
;
527 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD
:
529 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
530 cc_full_descr
->methods
.source
.query
=
531 cur_cc_descr_attr
->value
.source_query_method
;
533 case BT_COMPONENT_CLASS_TYPE_FILTER
:
534 cc_full_descr
->methods
.filter
.query
=
535 cur_cc_descr_attr
->value
.filter_query_method
;
537 case BT_COMPONENT_CLASS_TYPE_SINK
:
538 cc_full_descr
->methods
.sink
.query
=
539 cur_cc_descr_attr
->value
.sink_query_method
;
545 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INPUT_PORT_CONNECTED_METHOD
:
547 case BT_COMPONENT_CLASS_TYPE_FILTER
:
548 cc_full_descr
->methods
.filter
.input_port_connected
=
549 cur_cc_descr_attr
->value
.filter_input_port_connected_method
;
551 case BT_COMPONENT_CLASS_TYPE_SINK
:
552 cc_full_descr
->methods
.sink
.input_port_connected
=
553 cur_cc_descr_attr
->value
.sink_input_port_connected_method
;
559 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_OUTPUT_PORT_CONNECTED_METHOD
:
561 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
562 cc_full_descr
->methods
.source
.output_port_connected
=
563 cur_cc_descr_attr
->value
.source_output_port_connected_method
;
565 case BT_COMPONENT_CLASS_TYPE_FILTER
:
566 cc_full_descr
->methods
.filter
.output_port_connected
=
567 cur_cc_descr_attr
->value
.filter_output_port_connected_method
;
573 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GRAPH_IS_CONFIGURED_METHOD
:
575 case BT_COMPONENT_CLASS_TYPE_SINK
:
576 cc_full_descr
->methods
.sink
.graph_is_configured
=
577 cur_cc_descr_attr
->value
.sink_graph_is_configured_method
;
583 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_INIT_METHOD
:
585 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
586 cc_full_descr
->methods
.source
.msg_iter_init
=
587 cur_cc_descr_attr
->value
.source_msg_iter_init_method
;
589 case BT_COMPONENT_CLASS_TYPE_FILTER
:
590 cc_full_descr
->methods
.filter
.msg_iter_init
=
591 cur_cc_descr_attr
->value
.filter_msg_iter_init_method
;
597 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_FINALIZE_METHOD
:
599 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
600 cc_full_descr
->methods
.source
.msg_iter_finalize
=
601 cur_cc_descr_attr
->value
.source_msg_iter_finalize_method
;
603 case BT_COMPONENT_CLASS_TYPE_FILTER
:
604 cc_full_descr
->methods
.filter
.msg_iter_finalize
=
605 cur_cc_descr_attr
->value
.filter_msg_iter_finalize_method
;
611 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_NS_FROM_ORIGIN_METHOD
:
613 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
614 cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
=
615 cur_cc_descr_attr
->value
.source_msg_iter_seek_ns_from_origin_method
;
617 case BT_COMPONENT_CLASS_TYPE_FILTER
:
618 cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
=
619 cur_cc_descr_attr
->value
.filter_msg_iter_seek_ns_from_origin_method
;
625 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_BEGINNING_METHOD
:
627 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
628 cc_full_descr
->methods
.source
.msg_iter_seek_beginning
=
629 cur_cc_descr_attr
->value
.source_msg_iter_seek_beginning_method
;
631 case BT_COMPONENT_CLASS_TYPE_FILTER
:
632 cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
=
633 cur_cc_descr_attr
->value
.filter_msg_iter_seek_beginning_method
;
639 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_NS_FROM_ORIGIN_METHOD
:
641 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
642 cc_full_descr
->methods
.source
.msg_iter_can_seek_ns_from_origin
=
643 cur_cc_descr_attr
->value
.source_msg_iter_can_seek_ns_from_origin_method
;
645 case BT_COMPONENT_CLASS_TYPE_FILTER
:
646 cc_full_descr
->methods
.filter
.msg_iter_can_seek_ns_from_origin
=
647 cur_cc_descr_attr
->value
.filter_msg_iter_can_seek_ns_from_origin_method
;
653 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_BEGINNING_METHOD
:
655 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
656 cc_full_descr
->methods
.source
.msg_iter_can_seek_beginning
=
657 cur_cc_descr_attr
->value
.source_msg_iter_can_seek_beginning_method
;
659 case BT_COMPONENT_CLASS_TYPE_FILTER
:
660 cc_full_descr
->methods
.filter
.msg_iter_can_seek_beginning
=
661 cur_cc_descr_attr
->value
.filter_msg_iter_can_seek_beginning_method
;
668 if (fail_on_load_error
) {
669 BT_LIB_LOGW_APPEND_CAUSE(
670 "Unknown component class descriptor attribute: "
671 "plugin-path=\"%s\", "
672 "plugin-name=\"%s\", "
673 "comp-class-name=\"%s\", "
674 "comp-class-type=%s, "
675 "attr-type-name=\"%s\", "
677 spec
->shared_lib_handle
->path
?
678 spec
->shared_lib_handle
->path
->str
:
681 cur_cc_descr_attr
->comp_class_descriptor
->name
,
682 bt_component_class_type_string(
683 cur_cc_descr_attr
->comp_class_descriptor
->type
),
684 cur_cc_descr_attr
->type_name
,
685 cur_cc_descr_attr
->type
);
686 status
= BT_FUNC_STATUS_ERROR
;
690 "Ignoring unknown component class descriptor attribute: "
691 "plugin-path=\"%s\", "
692 "plugin-name=\"%s\", "
693 "comp-class-name=\"%s\", "
694 "comp-class-type=%s, "
695 "attr-type-name=\"%s\", "
697 spec
->shared_lib_handle
->path
?
698 spec
->shared_lib_handle
->path
->str
:
701 cur_cc_descr_attr
->comp_class_descriptor
->name
,
702 bt_component_class_type_string(
703 cur_cc_descr_attr
->comp_class_descriptor
->type
),
704 cur_cc_descr_attr
->type_name
,
705 cur_cc_descr_attr
->type
);
713 /* Initialize plugin */
715 enum bt_plugin_init_func_status init_status
;
717 BT_LOGD_STR("Calling user's plugin initialization function.");
718 init_status
= spec
->init((void *) plugin
);
719 BT_LOGD("User function returned: status=%s",
720 bt_common_func_status_string(init_status
));
722 if (init_status
< 0) {
723 if (fail_on_load_error
) {
724 BT_LIB_LOGW_APPEND_CAUSE(
725 "User's plugin initialization function failed: "
727 bt_common_func_status_string(init_status
));
728 status
= init_status
;
732 "User's plugin initialization function failed: "
734 bt_common_func_status_string(init_status
));
735 status
= BT_FUNC_STATUS_NOT_FOUND
;
742 spec
->shared_lib_handle
->init_called
= BT_TRUE
;
744 /* Add described component classes to plugin */
745 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
746 struct comp_class_full_descriptor
*cc_full_descr
=
747 &g_array_index(comp_class_full_descriptors
,
748 struct comp_class_full_descriptor
, i
);
749 struct bt_component_class
*comp_class
= NULL
;
750 struct bt_component_class_source
*src_comp_class
= NULL
;
751 struct bt_component_class_filter
*flt_comp_class
= NULL
;
752 struct bt_component_class_sink
*sink_comp_class
= NULL
;
754 BT_LOGI("Creating and setting properties of plugin's component class: "
755 "plugin-path=\"%s\", plugin-name=\"%s\", "
756 "comp-class-name=\"%s\", comp-class-type=%s",
757 spec
->shared_lib_handle
->path
?
758 spec
->shared_lib_handle
->path
->str
:
761 cc_full_descr
->descriptor
->name
,
762 bt_component_class_type_string(
763 cc_full_descr
->descriptor
->type
));
765 switch (cc_full_descr
->descriptor
->type
) {
766 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
767 src_comp_class
= bt_component_class_source_create(
768 cc_full_descr
->descriptor
->name
,
769 cc_full_descr
->descriptor
->methods
.source
.msg_iter_next
);
770 comp_class
= bt_component_class_source_as_component_class(
773 case BT_COMPONENT_CLASS_TYPE_FILTER
:
774 flt_comp_class
= bt_component_class_filter_create(
775 cc_full_descr
->descriptor
->name
,
776 cc_full_descr
->descriptor
->methods
.source
.msg_iter_next
);
777 comp_class
= bt_component_class_filter_as_component_class(
780 case BT_COMPONENT_CLASS_TYPE_SINK
:
781 sink_comp_class
= bt_component_class_sink_create(
782 cc_full_descr
->descriptor
->name
,
783 cc_full_descr
->descriptor
->methods
.sink
.consume
);
784 comp_class
= bt_component_class_sink_as_component_class(
788 if (fail_on_load_error
) {
789 BT_LIB_LOGW_APPEND_CAUSE(
790 "Unknown component class type: "
791 "plugin-path=\"%s\", plugin-name=\"%s\", "
792 "comp-class-name=\"%s\", comp-class-type=%d",
793 spec
->shared_lib_handle
->path
->str
?
794 spec
->shared_lib_handle
->path
->str
:
797 cc_full_descr
->descriptor
->name
,
798 cc_full_descr
->descriptor
->type
);
799 status
= BT_FUNC_STATUS_ERROR
;
803 "Ignoring unknown component class type: "
804 "plugin-path=\"%s\", plugin-name=\"%s\", "
805 "comp-class-name=\"%s\", comp-class-type=%d",
806 spec
->shared_lib_handle
->path
->str
?
807 spec
->shared_lib_handle
->path
->str
:
810 cc_full_descr
->descriptor
->name
,
811 cc_full_descr
->descriptor
->type
);
817 BT_LIB_LOGE_APPEND_CAUSE(
818 "Cannot create component class.");
819 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
823 if (cc_full_descr
->description
) {
824 ret
= bt_component_class_set_description(
825 comp_class
, cc_full_descr
->description
);
827 BT_LIB_LOGE_APPEND_CAUSE(
828 "Cannot set component class's description.");
829 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
830 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
835 if (cc_full_descr
->help
) {
836 ret
= bt_component_class_set_help(comp_class
,
837 cc_full_descr
->help
);
839 BT_LIB_LOGE_APPEND_CAUSE(
840 "Cannot set component class's help string.");
841 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
842 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
847 switch (cc_full_descr
->descriptor
->type
) {
848 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
849 if (cc_full_descr
->methods
.source
.init
) {
850 ret
= bt_component_class_source_set_init_method(
852 cc_full_descr
->methods
.source
.init
);
854 BT_LIB_LOGE_APPEND_CAUSE(
855 "Cannot set source component class's initialization method.");
856 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
857 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
862 if (cc_full_descr
->methods
.source
.finalize
) {
863 ret
= bt_component_class_source_set_finalize_method(
865 cc_full_descr
->methods
.source
.finalize
);
867 BT_LIB_LOGE_APPEND_CAUSE(
868 "Cannot set source component class's finalization method.");
869 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
870 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
875 if (cc_full_descr
->methods
.source
.query
) {
876 ret
= bt_component_class_source_set_query_method(
878 cc_full_descr
->methods
.source
.query
);
880 BT_LIB_LOGE_APPEND_CAUSE(
881 "Cannot set source component class's query method.");
882 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
883 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
888 if (cc_full_descr
->methods
.source
.output_port_connected
) {
889 ret
= bt_component_class_source_set_output_port_connected_method(
891 cc_full_descr
->methods
.source
.output_port_connected
);
893 BT_LIB_LOGE_APPEND_CAUSE(
894 "Cannot set source component class's \"output port connected\" method.");
895 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
896 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
901 if (cc_full_descr
->methods
.source
.msg_iter_init
) {
902 ret
= bt_component_class_source_set_message_iterator_init_method(
904 cc_full_descr
->methods
.source
.msg_iter_init
);
906 BT_LIB_LOGE_APPEND_CAUSE(
907 "Cannot set source component class's message iterator initialization method.");
908 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
909 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
914 if (cc_full_descr
->methods
.source
.msg_iter_finalize
) {
915 ret
= bt_component_class_source_set_message_iterator_finalize_method(
917 cc_full_descr
->methods
.source
.msg_iter_finalize
);
919 BT_LIB_LOGE_APPEND_CAUSE(
920 "Cannot set source component class's message iterator finalization method.");
921 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
922 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
927 if (cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
) {
928 ret
= bt_component_class_source_set_message_iterator_seek_ns_from_origin_method(
930 cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
);
932 BT_LIB_LOGE_APPEND_CAUSE(
933 "Cannot set source component class's message iterator \"seek nanoseconds from origin\" method.");
934 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
935 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
940 if (cc_full_descr
->methods
.source
.msg_iter_seek_beginning
) {
941 ret
= bt_component_class_source_set_message_iterator_seek_beginning_method(
943 cc_full_descr
->methods
.source
.msg_iter_seek_beginning
);
945 BT_LIB_LOGE_APPEND_CAUSE(
946 "Cannot set source component class's message iterator \"seek beginning\" method.");
947 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
948 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
953 if (cc_full_descr
->methods
.source
.msg_iter_can_seek_ns_from_origin
) {
954 ret
= bt_component_class_source_set_message_iterator_can_seek_ns_from_origin_method(
956 cc_full_descr
->methods
.source
.msg_iter_can_seek_ns_from_origin
);
958 BT_LIB_LOGE_APPEND_CAUSE(
959 "Cannot set source component class's message iterator \"can seek nanoseconds from origin\" method.");
960 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
961 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
966 if (cc_full_descr
->methods
.source
.msg_iter_can_seek_beginning
) {
967 ret
= bt_component_class_source_set_message_iterator_can_seek_beginning_method(
969 cc_full_descr
->methods
.source
.msg_iter_can_seek_beginning
);
971 BT_LIB_LOGE_APPEND_CAUSE(
972 "Cannot set source component class's message iterator \"can seek beginning\" method.");
973 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
974 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
980 case BT_COMPONENT_CLASS_TYPE_FILTER
:
981 if (cc_full_descr
->methods
.filter
.init
) {
982 ret
= bt_component_class_filter_set_init_method(
984 cc_full_descr
->methods
.filter
.init
);
986 BT_LIB_LOGE_APPEND_CAUSE(
987 "Cannot set filter component class's initialization method.");
988 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
989 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
994 if (cc_full_descr
->methods
.filter
.finalize
) {
995 ret
= bt_component_class_filter_set_finalize_method(
997 cc_full_descr
->methods
.filter
.finalize
);
999 BT_LIB_LOGE_APPEND_CAUSE(
1000 "Cannot set filter component class's finalization method.");
1001 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1002 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1007 if (cc_full_descr
->methods
.filter
.query
) {
1008 ret
= bt_component_class_filter_set_query_method(
1010 cc_full_descr
->methods
.filter
.query
);
1012 BT_LIB_LOGE_APPEND_CAUSE(
1013 "Cannot set filter component class's query method.");
1014 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1015 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1020 if (cc_full_descr
->methods
.filter
.input_port_connected
) {
1021 ret
= bt_component_class_filter_set_input_port_connected_method(
1023 cc_full_descr
->methods
.filter
.input_port_connected
);
1025 BT_LIB_LOGE_APPEND_CAUSE(
1026 "Cannot set filter component class's \"input port connected\" method.");
1027 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1028 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1033 if (cc_full_descr
->methods
.filter
.output_port_connected
) {
1034 ret
= bt_component_class_filter_set_output_port_connected_method(
1036 cc_full_descr
->methods
.filter
.output_port_connected
);
1038 BT_LIB_LOGE_APPEND_CAUSE(
1039 "Cannot set filter component class's \"output port connected\" method.");
1040 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1041 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1046 if (cc_full_descr
->methods
.filter
.msg_iter_init
) {
1047 ret
= bt_component_class_filter_set_message_iterator_init_method(
1049 cc_full_descr
->methods
.filter
.msg_iter_init
);
1051 BT_LIB_LOGE_APPEND_CAUSE(
1052 "Cannot set filter component class's message iterator initialization method.");
1053 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1054 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1059 if (cc_full_descr
->methods
.filter
.msg_iter_finalize
) {
1060 ret
= bt_component_class_filter_set_message_iterator_finalize_method(
1062 cc_full_descr
->methods
.filter
.msg_iter_finalize
);
1064 BT_LIB_LOGE_APPEND_CAUSE(
1065 "Cannot set filter component class's message iterator finalization method.");
1066 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1067 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1072 if (cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
) {
1073 ret
= bt_component_class_filter_set_message_iterator_seek_ns_from_origin_method(
1075 cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
);
1077 BT_LIB_LOGE_APPEND_CAUSE(
1078 "Cannot set filter component class's message iterator \"seek nanoseconds from origin\" method.");
1079 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1080 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1085 if (cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
) {
1086 ret
= bt_component_class_filter_set_message_iterator_seek_beginning_method(
1088 cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
);
1090 BT_LIB_LOGE_APPEND_CAUSE(
1091 "Cannot set filter component class's message iterator \"seek beginning\" method.");
1092 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1093 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1098 if (cc_full_descr
->methods
.filter
.msg_iter_can_seek_ns_from_origin
) {
1099 ret
= bt_component_class_filter_set_message_iterator_can_seek_ns_from_origin_method(
1101 cc_full_descr
->methods
.filter
.msg_iter_can_seek_ns_from_origin
);
1103 BT_LIB_LOGE_APPEND_CAUSE(
1104 "Cannot set filter component class's message iterator \"can seek nanoseconds from origin\" method.");
1105 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1106 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1111 if (cc_full_descr
->methods
.filter
.msg_iter_can_seek_beginning
) {
1112 ret
= bt_component_class_filter_set_message_iterator_can_seek_beginning_method(
1114 cc_full_descr
->methods
.filter
.msg_iter_can_seek_beginning
);
1116 BT_LIB_LOGE_APPEND_CAUSE(
1117 "Cannot set filter component class's message iterator \"can seek beginning\" method.");
1118 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1119 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1125 case BT_COMPONENT_CLASS_TYPE_SINK
:
1126 if (cc_full_descr
->methods
.sink
.init
) {
1127 ret
= bt_component_class_sink_set_init_method(
1129 cc_full_descr
->methods
.sink
.init
);
1131 BT_LIB_LOGE_APPEND_CAUSE(
1132 "Cannot set sink component class's initialization method.");
1133 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1134 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1139 if (cc_full_descr
->methods
.sink
.finalize
) {
1140 ret
= bt_component_class_sink_set_finalize_method(
1142 cc_full_descr
->methods
.sink
.finalize
);
1144 BT_LIB_LOGE_APPEND_CAUSE(
1145 "Cannot set sink component class's finalization method.");
1146 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1147 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1152 if (cc_full_descr
->methods
.sink
.query
) {
1153 ret
= bt_component_class_sink_set_query_method(
1155 cc_full_descr
->methods
.sink
.query
);
1157 BT_LIB_LOGE_APPEND_CAUSE(
1158 "Cannot set sink component class's query method.");
1159 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1160 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1165 if (cc_full_descr
->methods
.sink
.input_port_connected
) {
1166 ret
= bt_component_class_sink_set_input_port_connected_method(
1168 cc_full_descr
->methods
.sink
.input_port_connected
);
1170 BT_LIB_LOGE_APPEND_CAUSE(
1171 "Cannot set sink component class's \"input port connected\" method.");
1172 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1173 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1178 if (cc_full_descr
->methods
.sink
.graph_is_configured
) {
1179 ret
= bt_component_class_sink_set_graph_is_configured_method(
1181 cc_full_descr
->methods
.sink
.graph_is_configured
);
1183 BT_LIB_LOGE_APPEND_CAUSE(
1184 "Cannot set sink component class's \"graph is configured\" method.");
1185 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1186 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1197 * Add component class to the plugin object.
1199 * This will call back
1200 * bt_plugin_so_on_add_component_class() so that we can
1201 * add a mapping in the component class list when we
1202 * know the component class is successfully added.
1204 status
= bt_plugin_add_component_class(plugin
,
1205 (void *) comp_class
);
1206 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
1208 BT_LIB_LOGE_APPEND_CAUSE(
1209 "Cannot add component class to plugin.");
1215 g_array_free(comp_class_full_descriptors
, TRUE
);
1220 struct bt_plugin
*bt_plugin_so_create_empty(
1221 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
)
1223 struct bt_plugin
*plugin
;
1224 struct bt_plugin_so_spec_data
*spec
;
1226 plugin
= bt_plugin_create_empty(BT_PLUGIN_TYPE_SO
);
1231 plugin
->destroy_spec_data
= bt_plugin_so_destroy_spec_data
;
1232 plugin
->spec_data
= g_new0(struct bt_plugin_so_spec_data
, 1);
1233 if (!plugin
->spec_data
) {
1234 BT_LIB_LOGE_APPEND_CAUSE(
1235 "Failed to allocate one SO plugin specific data structure.");
1239 spec
= plugin
->spec_data
;
1240 spec
->shared_lib_handle
= shared_lib_handle
;
1241 bt_object_get_no_null_check(spec
->shared_lib_handle
);
1245 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1252 size_t count_non_null_items_in_section(const void *begin
, const void *end
)
1255 const int * const *begin_int
= (const int * const *) begin
;
1256 const int * const *end_int
= (const int * const *) end
;
1257 const int * const *iter
;
1259 for (iter
= begin_int
; iter
!= end_int
; iter
++) {
1269 int bt_plugin_so_create_all_from_sections(
1270 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
,
1271 bool fail_on_load_error
,
1272 struct __bt_plugin_descriptor
const * const *descriptors_begin
,
1273 struct __bt_plugin_descriptor
const * const *descriptors_end
,
1274 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
1275 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
1276 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
1277 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
1278 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
1279 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
,
1280 struct bt_plugin_set
**plugin_set_out
)
1282 int status
= BT_FUNC_STATUS_OK
;
1283 size_t descriptor_count
;
1285 size_t cc_descriptors_count
;
1286 size_t cc_descr_attrs_count
;
1289 BT_ASSERT(plugin_set_out
);
1290 *plugin_set_out
= NULL
;
1291 descriptor_count
= count_non_null_items_in_section(descriptors_begin
, descriptors_end
);
1292 attrs_count
= count_non_null_items_in_section(attrs_begin
, attrs_end
);
1293 cc_descriptors_count
= count_non_null_items_in_section(cc_descriptors_begin
, cc_descriptors_end
);
1294 cc_descr_attrs_count
= count_non_null_items_in_section(cc_descr_attrs_begin
, cc_descr_attrs_end
);
1295 BT_LOGI("Creating all SO plugins from sections: "
1296 "plugin-path=\"%s\", "
1297 "descr-begin-addr=%p, descr-end-addr=%p, "
1298 "attrs-begin-addr=%p, attrs-end-addr=%p, "
1299 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
1300 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p, "
1301 "descr-count=%zu, attrs-count=%zu, "
1302 "cc-descr-count=%zu, cc-descr-attrs-count=%zu",
1303 shared_lib_handle
->path
? shared_lib_handle
->path
->str
: NULL
,
1304 descriptors_begin
, descriptors_end
,
1305 attrs_begin
, attrs_end
,
1306 cc_descriptors_begin
, cc_descriptors_end
,
1307 cc_descr_attrs_begin
, cc_descr_attrs_end
,
1308 descriptor_count
, attrs_count
,
1309 cc_descriptors_count
, cc_descr_attrs_count
);
1310 *plugin_set_out
= bt_plugin_set_create();
1311 if (!*plugin_set_out
) {
1312 BT_LIB_LOGE_APPEND_CAUSE("Cannot create empty plugin set.");
1313 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1317 for (i
= 0; i
< descriptors_end
- descriptors_begin
; i
++) {
1318 const struct __bt_plugin_descriptor
*descriptor
=
1319 descriptors_begin
[i
];
1320 struct bt_plugin
*plugin
;
1326 BT_LOGI("Creating plugin object for plugin: "
1327 "name=\"%s\", abi-major=%d, abi-minor=%d",
1328 descriptor
->name
, descriptor
->major
, descriptor
->minor
);
1330 if (descriptor
->major
> __BT_PLUGIN_VERSION_MAJOR
) {
1331 if (fail_on_load_error
) {
1332 BT_LIB_LOGW_APPEND_CAUSE(
1333 "Unknown ABI major version: abi-major=%d",
1335 status
= BT_FUNC_STATUS_ERROR
;
1339 "Unknown ABI major version: abi-major=%d",
1345 plugin
= bt_plugin_so_create_empty(shared_lib_handle
);
1347 BT_LIB_LOGE_APPEND_CAUSE(
1348 "Cannot create empty shared library handle.");
1349 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1353 if (shared_lib_handle
->path
) {
1354 bt_plugin_set_path(plugin
,
1355 shared_lib_handle
->path
->str
);
1358 status
= bt_plugin_so_init(plugin
, fail_on_load_error
,
1359 descriptor
, attrs_begin
, attrs_end
,
1360 cc_descriptors_begin
, cc_descriptors_end
,
1361 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1362 if (status
== BT_FUNC_STATUS_OK
) {
1363 /* Add to plugin set */
1364 bt_plugin_set_add_plugin(*plugin_set_out
, plugin
);
1365 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1366 } else if (status
< 0) {
1368 * bt_plugin_so_init() handles
1369 * `fail_on_load_error`, so this is a "real"
1372 BT_LIB_LOGW_APPEND_CAUSE(
1373 "Cannot initialize SO plugin object from sections.");
1374 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1381 BT_ASSERT(*plugin_set_out
);
1383 if ((*plugin_set_out
)->plugins
->len
== 0) {
1384 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out
);
1385 status
= BT_FUNC_STATUS_NOT_FOUND
;
1391 BT_ASSERT(status
< 0);
1392 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out
);
1399 int bt_plugin_so_create_all_from_static(bool fail_on_load_error
,
1400 struct bt_plugin_set
**plugin_set_out
)
1403 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
1405 BT_ASSERT(plugin_set_out
);
1406 *plugin_set_out
= NULL
;
1407 status
= bt_plugin_so_shared_lib_handle_create(NULL
,
1408 &shared_lib_handle
);
1409 if (status
!= BT_FUNC_STATUS_OK
) {
1410 BT_ASSERT(!shared_lib_handle
);
1414 BT_ASSERT(shared_lib_handle
);
1415 BT_LOGD_STR("Creating all SO plugins from built-in plugins.");
1416 status
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
1418 __bt_get_begin_section_plugin_descriptors(),
1419 __bt_get_end_section_plugin_descriptors(),
1420 __bt_get_begin_section_plugin_descriptor_attributes(),
1421 __bt_get_end_section_plugin_descriptor_attributes(),
1422 __bt_get_begin_section_component_class_descriptors(),
1423 __bt_get_end_section_component_class_descriptors(),
1424 __bt_get_begin_section_component_class_descriptor_attributes(),
1425 __bt_get_end_section_component_class_descriptor_attributes(),
1427 BT_ASSERT((status
== BT_FUNC_STATUS_OK
&& *plugin_set_out
&&
1428 (*plugin_set_out
)->plugins
->len
> 0) || !*plugin_set_out
);
1431 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle
);
1436 int bt_plugin_so_create_all_from_file(const char *path
,
1437 bool fail_on_load_error
, struct bt_plugin_set
**plugin_set_out
)
1441 struct __bt_plugin_descriptor
const * const *descriptors_begin
= NULL
;
1442 struct __bt_plugin_descriptor
const * const *descriptors_end
= NULL
;
1443 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
= NULL
;
1444 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
= NULL
;
1445 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
= NULL
;
1446 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
= NULL
;
1447 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
= NULL
;
1448 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
= NULL
;
1449 struct __bt_plugin_descriptor
const * const *(*get_begin_section_plugin_descriptors
)(void);
1450 struct __bt_plugin_descriptor
const * const *(*get_end_section_plugin_descriptors
)(void);
1451 struct __bt_plugin_descriptor_attribute
const * const *(*get_begin_section_plugin_descriptor_attributes
)(void);
1452 struct __bt_plugin_descriptor_attribute
const * const *(*get_end_section_plugin_descriptor_attributes
)(void);
1453 struct __bt_plugin_component_class_descriptor
const * const *(*get_begin_section_component_class_descriptors
)(void);
1454 struct __bt_plugin_component_class_descriptor
const * const *(*get_end_section_component_class_descriptors
)(void);
1455 struct __bt_plugin_component_class_descriptor_attribute
const * const *(*get_begin_section_component_class_descriptor_attributes
)(void);
1456 struct __bt_plugin_component_class_descriptor_attribute
const * const *(*get_end_section_component_class_descriptor_attributes
)(void);
1457 bt_bool is_libtool_wrapper
= BT_FALSE
, is_shared_object
= BT_FALSE
;
1458 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
1461 BT_ASSERT(plugin_set_out
);
1462 *plugin_set_out
= NULL
;
1463 path_len
= strlen(path
);
1464 BT_ASSERT_PRE(path_len
> PLUGIN_SUFFIX_LEN
,
1465 "Path length is too short: path-length=%zu, min-length=%zu",
1466 path_len
, PLUGIN_SUFFIX_LEN
);
1467 BT_LOGI("Trying to create all SO plugins from file: path=\"%s\"", path
);
1471 * Check if the file ends with a known plugin file type suffix
1472 * (i.e. .so or .la on Linux).
1474 is_libtool_wrapper
= !strncmp(LIBTOOL_PLUGIN_SUFFIX
,
1475 path
+ path_len
- LIBTOOL_PLUGIN_SUFFIX_LEN
,
1476 LIBTOOL_PLUGIN_SUFFIX_LEN
);
1477 is_shared_object
= !strncmp(NATIVE_PLUGIN_SUFFIX
,
1478 path
+ path_len
- NATIVE_PLUGIN_SUFFIX_LEN
,
1479 NATIVE_PLUGIN_SUFFIX_LEN
);
1480 if (!is_shared_object
&& !is_libtool_wrapper
) {
1481 /* Name indicates this is not a plugin file; not an error */
1482 BT_LOGI("File is not an SO plugin file: path=\"%s\"", path
);
1483 status
= BT_FUNC_STATUS_NOT_FOUND
;
1487 status
= bt_plugin_so_shared_lib_handle_create(path
,
1488 &shared_lib_handle
);
1489 if (status
!= BT_FUNC_STATUS_OK
) {
1490 /* bt_plugin_so_shared_lib_handle_create() logs more details */
1491 BT_ASSERT(!shared_lib_handle
);
1495 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_plugin_descriptors",
1496 (gpointer
*) &get_begin_section_plugin_descriptors
)) {
1497 descriptors_begin
= get_begin_section_plugin_descriptors();
1500 * Use this first symbol to know whether or not this
1501 * shared object _looks like_ a Babeltrace plugin. Since
1502 * g_module_symbol() failed, assume that this is not a
1503 * Babeltrace plugin, so it's not an error.
1505 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1506 "symbol=\"%s\"", path
,
1507 "__bt_get_begin_section_plugin_descriptors");
1508 status
= BT_FUNC_STATUS_NOT_FOUND
;
1513 * If g_module_symbol() fails for any of the other symbols, fail
1514 * if `fail_on_load_error` is true.
1516 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_plugin_descriptors",
1517 (gpointer
*) &get_end_section_plugin_descriptors
)) {
1518 descriptors_end
= get_end_section_plugin_descriptors();
1520 if (fail_on_load_error
) {
1521 BT_LIB_LOGW_APPEND_CAUSE(
1522 "Cannot resolve plugin symbol: path=\"%s\", "
1523 "symbol=\"%s\"", path
,
1524 "__bt_get_end_section_plugin_descriptors");
1525 status
= BT_FUNC_STATUS_ERROR
;
1528 "Cannot resolve plugin symbol: path=\"%s\", "
1529 "symbol=\"%s\"", path
,
1530 "__bt_get_end_section_plugin_descriptors");
1531 status
= BT_FUNC_STATUS_NOT_FOUND
;
1537 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_plugin_descriptor_attributes",
1538 (gpointer
*) &get_begin_section_plugin_descriptor_attributes
)) {
1539 attrs_begin
= get_begin_section_plugin_descriptor_attributes();
1541 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1542 "symbol=\"%s\"", path
,
1543 "__bt_get_begin_section_plugin_descriptor_attributes");
1546 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_plugin_descriptor_attributes",
1547 (gpointer
*) &get_end_section_plugin_descriptor_attributes
)) {
1548 attrs_end
= get_end_section_plugin_descriptor_attributes();
1550 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1551 "symbol=\"%s\"", path
,
1552 "__bt_get_end_section_plugin_descriptor_attributes");
1555 if ((!!attrs_begin
- !!attrs_end
) != 0) {
1556 if (fail_on_load_error
) {
1557 BT_LIB_LOGW_APPEND_CAUSE(
1558 "Found section start or end symbol, but not both: "
1559 "path=\"%s\", symbol-start=\"%s\", "
1560 "symbol-end=\"%s\", symbol-start-addr=%p, "
1561 "symbol-end-addr=%p",
1562 path
, "__bt_get_begin_section_plugin_descriptor_attributes",
1563 "__bt_get_end_section_plugin_descriptor_attributes",
1564 attrs_begin
, attrs_end
);
1565 status
= BT_FUNC_STATUS_ERROR
;
1568 "Found section start or end symbol, but not both: "
1569 "path=\"%s\", symbol-start=\"%s\", "
1570 "symbol-end=\"%s\", symbol-start-addr=%p, "
1571 "symbol-end-addr=%p",
1572 path
, "__bt_get_begin_section_plugin_descriptor_attributes",
1573 "__bt_get_end_section_plugin_descriptor_attributes",
1574 attrs_begin
, attrs_end
);
1575 status
= BT_FUNC_STATUS_NOT_FOUND
;
1581 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_component_class_descriptors",
1582 (gpointer
*) &get_begin_section_component_class_descriptors
)) {
1583 cc_descriptors_begin
= get_begin_section_component_class_descriptors();
1585 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1586 "symbol=\"%s\"", path
,
1587 "__bt_get_begin_section_component_class_descriptors");
1590 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_component_class_descriptors",
1591 (gpointer
*) &get_end_section_component_class_descriptors
)) {
1592 cc_descriptors_end
= get_end_section_component_class_descriptors();
1594 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1595 "symbol=\"%s\"", path
,
1596 "__bt_get_end_section_component_class_descriptors");
1599 if ((!!cc_descriptors_begin
- !!cc_descriptors_end
) != 0) {
1600 if (fail_on_load_error
) {
1601 BT_LIB_LOGW_APPEND_CAUSE(
1602 "Found section start or end symbol, but not both: "
1603 "path=\"%s\", symbol-start=\"%s\", "
1604 "symbol-end=\"%s\", symbol-start-addr=%p, "
1605 "symbol-end-addr=%p",
1606 path
, "__bt_get_begin_section_component_class_descriptors",
1607 "__bt_get_end_section_component_class_descriptors",
1608 cc_descriptors_begin
, cc_descriptors_end
);
1609 status
= BT_FUNC_STATUS_ERROR
;
1612 "Found section start or end symbol, but not both: "
1613 "path=\"%s\", symbol-start=\"%s\", "
1614 "symbol-end=\"%s\", symbol-start-addr=%p, "
1615 "symbol-end-addr=%p",
1616 path
, "__bt_get_begin_section_component_class_descriptors",
1617 "__bt_get_end_section_component_class_descriptors",
1618 cc_descriptors_begin
, cc_descriptors_end
);
1619 status
= BT_FUNC_STATUS_NOT_FOUND
;
1625 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_component_class_descriptor_attributes",
1626 (gpointer
*) &get_begin_section_component_class_descriptor_attributes
)) {
1627 cc_descr_attrs_begin
= get_begin_section_component_class_descriptor_attributes();
1629 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1630 "symbol=\"%s\"", path
,
1631 "__bt_get_begin_section_component_class_descriptor_attributes");
1634 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_component_class_descriptor_attributes",
1635 (gpointer
*) &get_end_section_component_class_descriptor_attributes
)) {
1636 cc_descr_attrs_end
= get_end_section_component_class_descriptor_attributes();
1638 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1639 "symbol=\"%s\"", path
,
1640 "__bt_get_end_section_component_class_descriptor_attributes");
1643 if ((!!cc_descr_attrs_begin
- !!cc_descr_attrs_end
) != 0) {
1644 if (fail_on_load_error
) {
1645 BT_LIB_LOGW_APPEND_CAUSE(
1646 "Found section start or end symbol, but not both: "
1647 "path=\"%s\", symbol-start=\"%s\", "
1648 "symbol-end=\"%s\", symbol-start-addr=%p, "
1649 "symbol-end-addr=%p",
1650 path
, "__bt_get_begin_section_component_class_descriptor_attributes",
1651 "__bt_get_end_section_component_class_descriptor_attributes",
1652 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1653 status
= BT_FUNC_STATUS_ERROR
;
1656 "Found section start or end symbol, but not both: "
1657 "path=\"%s\", symbol-start=\"%s\", "
1658 "symbol-end=\"%s\", symbol-start-addr=%p, "
1659 "symbol-end-addr=%p",
1660 path
, "__bt_get_begin_section_component_class_descriptor_attributes",
1661 "__bt_get_end_section_component_class_descriptor_attributes",
1662 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1663 status
= BT_FUNC_STATUS_NOT_FOUND
;
1669 /* Initialize plugin */
1670 BT_LOGD_STR("Initializing plugin object.");
1671 status
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
1673 descriptors_begin
, descriptors_end
, attrs_begin
, attrs_end
,
1674 cc_descriptors_begin
, cc_descriptors_end
,
1675 cc_descr_attrs_begin
, cc_descr_attrs_end
, plugin_set_out
);
1678 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle
);
1683 void plugin_comp_class_destroy_listener(struct bt_component_class
*comp_class
,
1686 bt_list_del(&comp_class
->node
);
1687 BT_OBJECT_PUT_REF_AND_RESET(comp_class
->so_handle
);
1688 BT_LOGD("Component class destroyed: removed entry from list: "
1689 "comp-cls-addr=%p", comp_class
);
1692 void bt_plugin_so_on_add_component_class(struct bt_plugin
*plugin
,
1693 struct bt_component_class
*comp_class
)
1695 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
1697 BT_ASSERT(plugin
->spec_data
);
1698 BT_ASSERT(plugin
->type
== BT_PLUGIN_TYPE_SO
);
1700 bt_list_add(&comp_class
->node
, &component_class_list
);
1701 comp_class
->so_handle
= spec
->shared_lib_handle
;
1702 bt_object_get_no_null_check(comp_class
->so_handle
);
1704 /* Add our custom destroy listener */
1705 bt_component_class_add_destroy_listener(comp_class
,
1706 plugin_comp_class_destroy_listener
, NULL
);