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"
47 #include "plugin-so.h"
48 #include "lib/func-status.h"
49 #include "common/common.h"
51 #define NATIVE_PLUGIN_SUFFIX "." G_MODULE_SUFFIX
52 #define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
53 #define LIBTOOL_PLUGIN_SUFFIX ".la"
54 #define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
56 #define PLUGIN_SUFFIX_LEN bt_max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
57 sizeof(LIBTOOL_PLUGIN_SUFFIX))
62 * This list, global to the library, keeps all component classes that
63 * have a reference to their shared library handles. It allows iteration
64 * on all component classes still present when the destructor executes
65 * to release the shared library handle references they might still have.
67 * The list items are the component classes created with
68 * bt_plugin_add_component_class(). They keep the shared library handle
69 * object created by their plugin alive so that the plugin's code is
70 * not discarded when it could still be in use by living components
71 * created from those component classes:
73 * [component] --ref-> [component class]-> [shlib handle]
75 * It allows this use-case:
77 * my_plugins = bt_plugin_find_all_from_file("/path/to/my-plugin.so");
78 * // instantiate components from a plugin's component classes
79 * // put plugins and free my_plugins here
80 * // user code of instantiated components still exists
82 * An entry is removed from this list when a component class is
83 * destroyed thanks to a custom destroy listener. When the entry is
84 * removed, the entry is removed from the list, and we release the
85 * reference on the shlib handle. Assuming the original plugin object
86 * which contained some component classes is put first, when the last
87 * component class is removed from this list, the shared library handle
88 * object's reference count falls to zero and the shared library is
93 BT_LIST_HEAD(component_class_list
);
95 __attribute__((destructor
)) static
96 void fini_comp_class_list(void)
98 struct bt_component_class
*comp_class
, *tmp
;
100 bt_list_for_each_entry_safe(comp_class
, tmp
, &component_class_list
, node
) {
101 bt_list_del(&comp_class
->node
);
102 BT_OBJECT_PUT_REF_AND_RESET(comp_class
->so_handle
);
105 BT_LOGD_STR("Released references from all component classes to shared library handles.");
109 void bt_plugin_so_shared_lib_handle_destroy(struct bt_object
*obj
)
111 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
;
114 shared_lib_handle
= container_of(obj
,
115 struct bt_plugin_so_shared_lib_handle
, base
);
116 const char *path
= shared_lib_handle
->path
?
117 shared_lib_handle
->path
->str
: NULL
;
119 BT_LOGI("Destroying shared library handle: addr=%p, path=\"%s\"",
120 shared_lib_handle
, path
);
122 if (shared_lib_handle
->init_called
&& shared_lib_handle
->exit
) {
123 BT_LOGD_STR("Calling user's plugin exit function.");
124 shared_lib_handle
->exit();
125 BT_LOGD_STR("User function returned.");
128 if (shared_lib_handle
->module
) {
131 * Valgrind shows incomplete stack traces when
132 * dynamically loaded libraries are closed before it
133 * finishes. Use the LIBBABELTRACE2_NO_DLCLOSE in a debug
134 * build to avoid this.
136 const char *var
= getenv("LIBBABELTRACE2_NO_DLCLOSE");
138 if (!var
|| strcmp(var
, "1") != 0) {
140 BT_LOGI("Closing GModule: path=\"%s\"", path
);
142 if (!g_module_close(shared_lib_handle
->module
)) {
144 * Just log here: we're in a destructor,
145 * so we cannot append an error cause
146 * (there's no returned status).
148 BT_LOGE("Cannot close GModule: %s: path=\"%s\"",
149 g_module_error(), path
);
152 shared_lib_handle
->module
= NULL
;
155 BT_LOGI("Not closing GModule because `LIBBABELTRACE2_NO_DLCLOSE=1`: "
156 "path=\"%s\"", path
);
161 if (shared_lib_handle
->path
) {
162 g_string_free(shared_lib_handle
->path
, TRUE
);
163 shared_lib_handle
->path
= NULL
;
166 g_free(shared_lib_handle
);
170 int bt_plugin_so_shared_lib_handle_create(
172 struct bt_plugin_so_shared_lib_handle
**shared_lib_handle
)
174 int status
= BT_FUNC_STATUS_OK
;
176 BT_ASSERT(shared_lib_handle
);
177 BT_LOGI("Creating shared library handle: path=\"%s\"", path
);
178 *shared_lib_handle
= g_new0(struct bt_plugin_so_shared_lib_handle
, 1);
179 if (!*shared_lib_handle
) {
180 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one shared library handle.");
181 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
185 bt_object_init_shared(&(*shared_lib_handle
)->base
,
186 bt_plugin_so_shared_lib_handle_destroy
);
192 (*shared_lib_handle
)->path
= g_string_new(path
);
193 if (!(*shared_lib_handle
)->path
) {
194 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
195 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
199 (*shared_lib_handle
)->module
= g_module_open(path
, G_MODULE_BIND_LOCAL
);
200 if (!(*shared_lib_handle
)->module
) {
202 * INFO-level logging because we're only _trying_ to
203 * open this file as a Babeltrace plugin: if it's not,
204 * it's not an error. And because this can be tried
205 * during bt_plugin_find_all_from_dir(), it's not even a
208 BT_LOGI("Cannot open GModule: %s: path=\"%s\"",
209 g_module_error(), path
);
210 BT_OBJECT_PUT_REF_AND_RESET(*shared_lib_handle
);
211 status
= BT_FUNC_STATUS_NOT_FOUND
;
218 BT_ASSERT(*shared_lib_handle
|| status
!= BT_FUNC_STATUS_OK
);
219 if (*shared_lib_handle
) {
220 BT_LOGI("Created shared library handle: path=\"%s\", addr=%p",
221 path
, *shared_lib_handle
);
228 void bt_plugin_so_destroy_spec_data(struct bt_plugin
*plugin
)
230 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
232 if (!plugin
->spec_data
) {
236 BT_ASSERT(plugin
->type
== BT_PLUGIN_TYPE_SO
);
238 BT_OBJECT_PUT_REF_AND_RESET(spec
->shared_lib_handle
);
239 g_free(plugin
->spec_data
);
240 plugin
->spec_data
= NULL
;
244 * This function does the following:
246 * 1. Iterate on the plugin descriptor attributes section and set the
247 * plugin's attributes depending on the attribute types. This
248 * includes the name of the plugin, its description, and its
249 * initialization function, for example.
251 * 2. Iterate on the component class descriptors section and create one
252 * "full descriptor" (temporary structure) for each one that is found
253 * and attached to our plugin descriptor.
255 * 3. Iterate on the component class descriptor attributes section and
256 * set the corresponding full descriptor's attributes depending on
257 * the attribute types. This includes the description of the
258 * component class, as well as its initialization and destroy
261 * 4. Call the user's plugin initialization function, if any is
264 * 5. For each full component class descriptor, create a component class
265 * object, set its optional attributes, and add it to the plugin
268 * 6. Freeze the plugin object.
271 int bt_plugin_so_init(struct bt_plugin
*plugin
,
272 bool fail_on_load_error
,
273 const struct __bt_plugin_descriptor
*descriptor
,
274 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
275 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
276 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
277 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
278 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
279 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
)
282 * This structure's members point to the plugin's memory
285 struct comp_class_full_descriptor
{
286 const struct __bt_plugin_component_class_descriptor
*descriptor
;
287 const char *description
;
292 bt_component_class_source_get_supported_mip_versions_method get_supported_mip_versions
;
293 bt_component_class_source_initialize_method init
;
294 bt_component_class_source_finalize_method finalize
;
295 bt_component_class_source_query_method query
;
296 bt_component_class_source_output_port_connected_method output_port_connected
;
297 bt_component_class_source_message_iterator_initialize_method msg_iter_initialize
;
298 bt_component_class_source_message_iterator_finalize_method msg_iter_finalize
;
299 bt_component_class_source_message_iterator_seek_ns_from_origin_method msg_iter_seek_ns_from_origin
;
300 bt_component_class_source_message_iterator_seek_beginning_method msg_iter_seek_beginning
;
301 bt_component_class_source_message_iterator_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin
;
302 bt_component_class_source_message_iterator_can_seek_beginning_method msg_iter_can_seek_beginning
;
306 bt_component_class_filter_get_supported_mip_versions_method get_supported_mip_versions
;
307 bt_component_class_filter_initialize_method init
;
308 bt_component_class_filter_finalize_method finalize
;
309 bt_component_class_filter_query_method query
;
310 bt_component_class_filter_input_port_connected_method input_port_connected
;
311 bt_component_class_filter_output_port_connected_method output_port_connected
;
312 bt_component_class_filter_message_iterator_initialize_method msg_iter_initialize
;
313 bt_component_class_filter_message_iterator_finalize_method msg_iter_finalize
;
314 bt_component_class_filter_message_iterator_seek_ns_from_origin_method msg_iter_seek_ns_from_origin
;
315 bt_component_class_filter_message_iterator_seek_beginning_method msg_iter_seek_beginning
;
316 bt_component_class_filter_message_iterator_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin
;
317 bt_component_class_filter_message_iterator_can_seek_beginning_method msg_iter_can_seek_beginning
;
321 bt_component_class_sink_get_supported_mip_versions_method get_supported_mip_versions
;
322 bt_component_class_sink_initialize_method init
;
323 bt_component_class_sink_finalize_method finalize
;
324 bt_component_class_sink_query_method query
;
325 bt_component_class_sink_input_port_connected_method input_port_connected
;
326 bt_component_class_sink_graph_is_configured_method graph_is_configured
;
331 int status
= BT_FUNC_STATUS_OK
;
332 struct __bt_plugin_descriptor_attribute
const * const *cur_attr_ptr
;
333 struct __bt_plugin_component_class_descriptor
const * const *cur_cc_descr_ptr
;
334 struct __bt_plugin_component_class_descriptor_attribute
const * const *cur_cc_descr_attr_ptr
;
335 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
336 GArray
*comp_class_full_descriptors
;
340 BT_LOGI("Initializing plugin object from descriptors found in sections: "
341 "plugin-addr=%p, plugin-path=\"%s\", "
342 "attrs-begin-addr=%p, attrs-end-addr=%p, "
343 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
344 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p",
346 spec
->shared_lib_handle
->path
?
347 spec
->shared_lib_handle
->path
->str
: NULL
,
348 attrs_begin
, attrs_end
,
349 cc_descriptors_begin
, cc_descriptors_end
,
350 cc_descr_attrs_begin
, cc_descr_attrs_end
);
351 comp_class_full_descriptors
= g_array_new(FALSE
, TRUE
,
352 sizeof(struct comp_class_full_descriptor
));
353 if (!comp_class_full_descriptors
) {
354 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
355 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
359 /* Set mandatory attributes */
360 spec
->descriptor
= descriptor
;
361 bt_plugin_set_name(plugin
, descriptor
->name
);
364 * Find and set optional attributes attached to this plugin
367 for (cur_attr_ptr
= attrs_begin
; cur_attr_ptr
!= attrs_end
; cur_attr_ptr
++) {
368 const struct __bt_plugin_descriptor_attribute
*cur_attr
=
375 if (cur_attr
->plugin_descriptor
!= descriptor
) {
379 switch (cur_attr
->type
) {
380 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT
:
381 spec
->init
= cur_attr
->value
.init
;
383 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT
:
384 spec
->shared_lib_handle
->exit
= cur_attr
->value
.exit
;
386 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR
:
387 bt_plugin_set_author(plugin
, cur_attr
->value
.author
);
389 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE
:
390 bt_plugin_set_license(plugin
, cur_attr
->value
.license
);
392 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
393 bt_plugin_set_description(plugin
, cur_attr
->value
.description
);
395 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION
:
396 bt_plugin_set_version(plugin
,
397 (unsigned int) cur_attr
->value
.version
.major
,
398 (unsigned int) cur_attr
->value
.version
.minor
,
399 (unsigned int) cur_attr
->value
.version
.patch
,
400 cur_attr
->value
.version
.extra
);
403 if (fail_on_load_error
) {
404 BT_LIB_LOGW_APPEND_CAUSE(
405 "Unknown plugin descriptor attribute: "
406 "plugin-path=\"%s\", plugin-name=\"%s\", "
407 "attr-type-name=\"%s\", attr-type-id=%d",
408 spec
->shared_lib_handle
->path
?
409 spec
->shared_lib_handle
->path
->str
:
411 descriptor
->name
, cur_attr
->type_name
,
413 status
= BT_FUNC_STATUS_ERROR
;
417 "Ignoring unknown plugin descriptor attribute: "
418 "plugin-path=\"%s\", plugin-name=\"%s\", "
419 "attr-type-name=\"%s\", attr-type-id=%d",
420 spec
->shared_lib_handle
->path
?
421 spec
->shared_lib_handle
->path
->str
:
423 descriptor
->name
, cur_attr
->type_name
,
432 * Find component class descriptors attached to this plugin
433 * descriptor and initialize corresponding full component class
434 * descriptors in the array.
436 for (cur_cc_descr_ptr
= cc_descriptors_begin
; cur_cc_descr_ptr
!= cc_descriptors_end
; cur_cc_descr_ptr
++) {
437 const struct __bt_plugin_component_class_descriptor
*cur_cc_descr
=
439 struct comp_class_full_descriptor full_descriptor
= {0};
445 if (cur_cc_descr
->plugin_descriptor
!= descriptor
) {
449 full_descriptor
.descriptor
= cur_cc_descr
;
450 g_array_append_val(comp_class_full_descriptors
,
455 * Find component class descriptor attributes attached to this
456 * plugin descriptor and update corresponding full component
457 * class descriptors in the array.
459 for (cur_cc_descr_attr_ptr
= cc_descr_attrs_begin
; cur_cc_descr_attr_ptr
!= cc_descr_attrs_end
; cur_cc_descr_attr_ptr
++) {
460 const struct __bt_plugin_component_class_descriptor_attribute
*cur_cc_descr_attr
=
461 *cur_cc_descr_attr_ptr
;
462 enum bt_component_class_type cc_type
;
464 if (!cur_cc_descr_attr
) {
468 if (cur_cc_descr_attr
->comp_class_descriptor
->plugin_descriptor
!=
473 cc_type
= cur_cc_descr_attr
->comp_class_descriptor
->type
;
475 /* Find the corresponding component class descriptor entry */
476 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
477 struct comp_class_full_descriptor
*cc_full_descr
=
478 &g_array_index(comp_class_full_descriptors
,
479 struct comp_class_full_descriptor
, i
);
481 if (cur_cc_descr_attr
->comp_class_descriptor
!=
482 cc_full_descr
->descriptor
) {
486 switch (cur_cc_descr_attr
->type
) {
487 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
488 cc_full_descr
->description
=
489 cur_cc_descr_attr
->value
.description
;
491 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP
:
492 cc_full_descr
->help
=
493 cur_cc_descr_attr
->value
.help
;
495 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GET_SUPPORTED_MIP_VERSIONS_METHOD
:
497 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
498 cc_full_descr
->methods
.source
.get_supported_mip_versions
=
499 cur_cc_descr_attr
->value
.source_get_supported_mip_versions_method
;
501 case BT_COMPONENT_CLASS_TYPE_FILTER
:
502 cc_full_descr
->methods
.filter
.get_supported_mip_versions
=
503 cur_cc_descr_attr
->value
.filter_get_supported_mip_versions_method
;
505 case BT_COMPONENT_CLASS_TYPE_SINK
:
506 cc_full_descr
->methods
.sink
.get_supported_mip_versions
=
507 cur_cc_descr_attr
->value
.sink_get_supported_mip_versions_method
;
513 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INITIALIZE_METHOD
:
515 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
516 cc_full_descr
->methods
.source
.init
=
517 cur_cc_descr_attr
->value
.source_initialize_method
;
519 case BT_COMPONENT_CLASS_TYPE_FILTER
:
520 cc_full_descr
->methods
.filter
.init
=
521 cur_cc_descr_attr
->value
.filter_initialize_method
;
523 case BT_COMPONENT_CLASS_TYPE_SINK
:
524 cc_full_descr
->methods
.sink
.init
=
525 cur_cc_descr_attr
->value
.sink_initialize_method
;
531 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD
:
533 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
534 cc_full_descr
->methods
.source
.finalize
=
535 cur_cc_descr_attr
->value
.source_finalize_method
;
537 case BT_COMPONENT_CLASS_TYPE_FILTER
:
538 cc_full_descr
->methods
.filter
.finalize
=
539 cur_cc_descr_attr
->value
.filter_finalize_method
;
541 case BT_COMPONENT_CLASS_TYPE_SINK
:
542 cc_full_descr
->methods
.sink
.finalize
=
543 cur_cc_descr_attr
->value
.sink_finalize_method
;
549 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD
:
551 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
552 cc_full_descr
->methods
.source
.query
=
553 cur_cc_descr_attr
->value
.source_query_method
;
555 case BT_COMPONENT_CLASS_TYPE_FILTER
:
556 cc_full_descr
->methods
.filter
.query
=
557 cur_cc_descr_attr
->value
.filter_query_method
;
559 case BT_COMPONENT_CLASS_TYPE_SINK
:
560 cc_full_descr
->methods
.sink
.query
=
561 cur_cc_descr_attr
->value
.sink_query_method
;
567 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INPUT_PORT_CONNECTED_METHOD
:
569 case BT_COMPONENT_CLASS_TYPE_FILTER
:
570 cc_full_descr
->methods
.filter
.input_port_connected
=
571 cur_cc_descr_attr
->value
.filter_input_port_connected_method
;
573 case BT_COMPONENT_CLASS_TYPE_SINK
:
574 cc_full_descr
->methods
.sink
.input_port_connected
=
575 cur_cc_descr_attr
->value
.sink_input_port_connected_method
;
581 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_OUTPUT_PORT_CONNECTED_METHOD
:
583 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
584 cc_full_descr
->methods
.source
.output_port_connected
=
585 cur_cc_descr_attr
->value
.source_output_port_connected_method
;
587 case BT_COMPONENT_CLASS_TYPE_FILTER
:
588 cc_full_descr
->methods
.filter
.output_port_connected
=
589 cur_cc_descr_attr
->value
.filter_output_port_connected_method
;
595 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GRAPH_IS_CONFIGURED_METHOD
:
597 case BT_COMPONENT_CLASS_TYPE_SINK
:
598 cc_full_descr
->methods
.sink
.graph_is_configured
=
599 cur_cc_descr_attr
->value
.sink_graph_is_configured_method
;
605 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_INITIALIZE_METHOD
:
607 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
608 cc_full_descr
->methods
.source
.msg_iter_initialize
=
609 cur_cc_descr_attr
->value
.source_msg_iter_initialize_method
;
611 case BT_COMPONENT_CLASS_TYPE_FILTER
:
612 cc_full_descr
->methods
.filter
.msg_iter_initialize
=
613 cur_cc_descr_attr
->value
.filter_msg_iter_initialize_method
;
619 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_FINALIZE_METHOD
:
621 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
622 cc_full_descr
->methods
.source
.msg_iter_finalize
=
623 cur_cc_descr_attr
->value
.source_msg_iter_finalize_method
;
625 case BT_COMPONENT_CLASS_TYPE_FILTER
:
626 cc_full_descr
->methods
.filter
.msg_iter_finalize
=
627 cur_cc_descr_attr
->value
.filter_msg_iter_finalize_method
;
633 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_NS_FROM_ORIGIN_METHOD
:
635 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
636 cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
=
637 cur_cc_descr_attr
->value
.source_msg_iter_seek_ns_from_origin_method
;
639 case BT_COMPONENT_CLASS_TYPE_FILTER
:
640 cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
=
641 cur_cc_descr_attr
->value
.filter_msg_iter_seek_ns_from_origin_method
;
647 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_BEGINNING_METHOD
:
649 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
650 cc_full_descr
->methods
.source
.msg_iter_seek_beginning
=
651 cur_cc_descr_attr
->value
.source_msg_iter_seek_beginning_method
;
653 case BT_COMPONENT_CLASS_TYPE_FILTER
:
654 cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
=
655 cur_cc_descr_attr
->value
.filter_msg_iter_seek_beginning_method
;
661 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_NS_FROM_ORIGIN_METHOD
:
663 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
664 cc_full_descr
->methods
.source
.msg_iter_can_seek_ns_from_origin
=
665 cur_cc_descr_attr
->value
.source_msg_iter_can_seek_ns_from_origin_method
;
667 case BT_COMPONENT_CLASS_TYPE_FILTER
:
668 cc_full_descr
->methods
.filter
.msg_iter_can_seek_ns_from_origin
=
669 cur_cc_descr_attr
->value
.filter_msg_iter_can_seek_ns_from_origin_method
;
675 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_BEGINNING_METHOD
:
677 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
678 cc_full_descr
->methods
.source
.msg_iter_can_seek_beginning
=
679 cur_cc_descr_attr
->value
.source_msg_iter_can_seek_beginning_method
;
681 case BT_COMPONENT_CLASS_TYPE_FILTER
:
682 cc_full_descr
->methods
.filter
.msg_iter_can_seek_beginning
=
683 cur_cc_descr_attr
->value
.filter_msg_iter_can_seek_beginning_method
;
690 if (fail_on_load_error
) {
691 BT_LIB_LOGW_APPEND_CAUSE(
692 "Unknown component class descriptor attribute: "
693 "plugin-path=\"%s\", "
694 "plugin-name=\"%s\", "
695 "comp-class-name=\"%s\", "
696 "comp-class-type=%s, "
697 "attr-type-name=\"%s\", "
699 spec
->shared_lib_handle
->path
?
700 spec
->shared_lib_handle
->path
->str
:
703 cur_cc_descr_attr
->comp_class_descriptor
->name
,
704 bt_component_class_type_string(
705 cur_cc_descr_attr
->comp_class_descriptor
->type
),
706 cur_cc_descr_attr
->type_name
,
707 cur_cc_descr_attr
->type
);
708 status
= BT_FUNC_STATUS_ERROR
;
712 "Ignoring unknown component class descriptor attribute: "
713 "plugin-path=\"%s\", "
714 "plugin-name=\"%s\", "
715 "comp-class-name=\"%s\", "
716 "comp-class-type=%s, "
717 "attr-type-name=\"%s\", "
719 spec
->shared_lib_handle
->path
?
720 spec
->shared_lib_handle
->path
->str
:
723 cur_cc_descr_attr
->comp_class_descriptor
->name
,
724 bt_component_class_type_string(
725 cur_cc_descr_attr
->comp_class_descriptor
->type
),
726 cur_cc_descr_attr
->type_name
,
727 cur_cc_descr_attr
->type
);
735 /* Initialize plugin */
737 enum bt_plugin_initialize_func_status init_status
;
739 BT_LOGD_STR("Calling user's plugin initialization function.");
740 init_status
= spec
->init((void *) plugin
);
741 BT_LOGD("User function returned: status=%s",
742 bt_common_func_status_string(init_status
));
744 if (init_status
< 0) {
745 if (fail_on_load_error
) {
746 BT_LIB_LOGW_APPEND_CAUSE(
747 "User's plugin initialization function failed: "
749 bt_common_func_status_string(init_status
));
750 status
= init_status
;
754 "User's plugin initialization function failed: "
756 bt_common_func_status_string(init_status
));
757 status
= BT_FUNC_STATUS_NOT_FOUND
;
764 spec
->shared_lib_handle
->init_called
= BT_TRUE
;
766 /* Add described component classes to plugin */
767 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
768 struct comp_class_full_descriptor
*cc_full_descr
=
769 &g_array_index(comp_class_full_descriptors
,
770 struct comp_class_full_descriptor
, i
);
771 struct bt_component_class
*comp_class
= NULL
;
772 struct bt_component_class_source
*src_comp_class
= NULL
;
773 struct bt_component_class_filter
*flt_comp_class
= NULL
;
774 struct bt_component_class_sink
*sink_comp_class
= NULL
;
776 BT_LOGI("Creating and setting properties of plugin's component class: "
777 "plugin-path=\"%s\", plugin-name=\"%s\", "
778 "comp-class-name=\"%s\", comp-class-type=%s",
779 spec
->shared_lib_handle
->path
?
780 spec
->shared_lib_handle
->path
->str
:
783 cc_full_descr
->descriptor
->name
,
784 bt_component_class_type_string(
785 cc_full_descr
->descriptor
->type
));
787 switch (cc_full_descr
->descriptor
->type
) {
788 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
789 src_comp_class
= bt_component_class_source_create(
790 cc_full_descr
->descriptor
->name
,
791 cc_full_descr
->descriptor
->methods
.source
.msg_iter_next
);
792 comp_class
= bt_component_class_source_as_component_class(
795 case BT_COMPONENT_CLASS_TYPE_FILTER
:
796 flt_comp_class
= bt_component_class_filter_create(
797 cc_full_descr
->descriptor
->name
,
798 cc_full_descr
->descriptor
->methods
.source
.msg_iter_next
);
799 comp_class
= bt_component_class_filter_as_component_class(
802 case BT_COMPONENT_CLASS_TYPE_SINK
:
803 sink_comp_class
= bt_component_class_sink_create(
804 cc_full_descr
->descriptor
->name
,
805 cc_full_descr
->descriptor
->methods
.sink
.consume
);
806 comp_class
= bt_component_class_sink_as_component_class(
810 if (fail_on_load_error
) {
811 BT_LIB_LOGW_APPEND_CAUSE(
812 "Unknown component class type: "
813 "plugin-path=\"%s\", plugin-name=\"%s\", "
814 "comp-class-name=\"%s\", comp-class-type=%d",
815 spec
->shared_lib_handle
->path
->str
?
816 spec
->shared_lib_handle
->path
->str
:
819 cc_full_descr
->descriptor
->name
,
820 cc_full_descr
->descriptor
->type
);
821 status
= BT_FUNC_STATUS_ERROR
;
825 "Ignoring unknown component class type: "
826 "plugin-path=\"%s\", plugin-name=\"%s\", "
827 "comp-class-name=\"%s\", comp-class-type=%d",
828 spec
->shared_lib_handle
->path
->str
?
829 spec
->shared_lib_handle
->path
->str
:
832 cc_full_descr
->descriptor
->name
,
833 cc_full_descr
->descriptor
->type
);
839 BT_LIB_LOGE_APPEND_CAUSE(
840 "Cannot create component class.");
841 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
845 if (cc_full_descr
->description
) {
846 ret
= bt_component_class_set_description(
847 comp_class
, cc_full_descr
->description
);
849 BT_LIB_LOGE_APPEND_CAUSE(
850 "Cannot set component class's description.");
851 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
852 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
857 if (cc_full_descr
->help
) {
858 ret
= bt_component_class_set_help(comp_class
,
859 cc_full_descr
->help
);
861 BT_LIB_LOGE_APPEND_CAUSE(
862 "Cannot set component class's help string.");
863 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
864 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
869 switch (cc_full_descr
->descriptor
->type
) {
870 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
871 if (cc_full_descr
->methods
.source
.get_supported_mip_versions
) {
872 ret
= bt_component_class_source_set_get_supported_mip_versions_method(
874 cc_full_descr
->methods
.source
.get_supported_mip_versions
);
876 BT_LIB_LOGE_APPEND_CAUSE(
877 "Cannot set source component class's \"get supported MIP versions\" method.");
878 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
879 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
884 if (cc_full_descr
->methods
.source
.init
) {
885 ret
= bt_component_class_source_set_initialize_method(
887 cc_full_descr
->methods
.source
.init
);
889 BT_LIB_LOGE_APPEND_CAUSE(
890 "Cannot set source component class's initialization method.");
891 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
892 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
897 if (cc_full_descr
->methods
.source
.finalize
) {
898 ret
= bt_component_class_source_set_finalize_method(
900 cc_full_descr
->methods
.source
.finalize
);
902 BT_LIB_LOGE_APPEND_CAUSE(
903 "Cannot set source component class's finalization method.");
904 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
905 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
910 if (cc_full_descr
->methods
.source
.query
) {
911 ret
= bt_component_class_source_set_query_method(
913 cc_full_descr
->methods
.source
.query
);
915 BT_LIB_LOGE_APPEND_CAUSE(
916 "Cannot set source component class's query method.");
917 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
918 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
923 if (cc_full_descr
->methods
.source
.output_port_connected
) {
924 ret
= bt_component_class_source_set_output_port_connected_method(
926 cc_full_descr
->methods
.source
.output_port_connected
);
928 BT_LIB_LOGE_APPEND_CAUSE(
929 "Cannot set source component class's \"output port connected\" method.");
930 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
931 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
936 if (cc_full_descr
->methods
.source
.msg_iter_initialize
) {
937 ret
= bt_component_class_source_set_message_iterator_initialize_method(
939 cc_full_descr
->methods
.source
.msg_iter_initialize
);
941 BT_LIB_LOGE_APPEND_CAUSE(
942 "Cannot set source component class's message iterator initialization method.");
943 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
944 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
949 if (cc_full_descr
->methods
.source
.msg_iter_finalize
) {
950 ret
= bt_component_class_source_set_message_iterator_finalize_method(
952 cc_full_descr
->methods
.source
.msg_iter_finalize
);
954 BT_LIB_LOGE_APPEND_CAUSE(
955 "Cannot set source component class's message iterator finalization method.");
956 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
957 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
962 if (cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
) {
963 ret
= bt_component_class_source_set_message_iterator_seek_ns_from_origin_methods(
965 cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
,
966 cc_full_descr
->methods
.source
.msg_iter_can_seek_ns_from_origin
);
968 BT_LIB_LOGE_APPEND_CAUSE(
969 "Cannot set source component class's message iterator \"seek nanoseconds from origin\" methods.");
970 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
971 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
976 if (cc_full_descr
->methods
.source
.msg_iter_seek_beginning
) {
977 ret
= bt_component_class_source_set_message_iterator_seek_beginning_methods(
979 cc_full_descr
->methods
.source
.msg_iter_seek_beginning
,
980 cc_full_descr
->methods
.source
.msg_iter_can_seek_beginning
);
982 BT_LIB_LOGE_APPEND_CAUSE(
983 "Cannot set source component class's message iterator \"seek beginning\" methods.");
984 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
985 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
991 case BT_COMPONENT_CLASS_TYPE_FILTER
:
992 if (cc_full_descr
->methods
.filter
.get_supported_mip_versions
) {
993 ret
= bt_component_class_filter_set_get_supported_mip_versions_method(
995 cc_full_descr
->methods
.filter
.get_supported_mip_versions
);
997 BT_LIB_LOGE_APPEND_CAUSE(
998 "Cannot set filter component class's \"get supported MIP versions\" method.");
999 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1000 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1005 if (cc_full_descr
->methods
.filter
.init
) {
1006 ret
= bt_component_class_filter_set_initialize_method(
1008 cc_full_descr
->methods
.filter
.init
);
1010 BT_LIB_LOGE_APPEND_CAUSE(
1011 "Cannot set filter component class's initialization method.");
1012 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1013 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1018 if (cc_full_descr
->methods
.filter
.finalize
) {
1019 ret
= bt_component_class_filter_set_finalize_method(
1021 cc_full_descr
->methods
.filter
.finalize
);
1023 BT_LIB_LOGE_APPEND_CAUSE(
1024 "Cannot set filter component class's finalization method.");
1025 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1026 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1031 if (cc_full_descr
->methods
.filter
.query
) {
1032 ret
= bt_component_class_filter_set_query_method(
1034 cc_full_descr
->methods
.filter
.query
);
1036 BT_LIB_LOGE_APPEND_CAUSE(
1037 "Cannot set filter component class's query method.");
1038 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1039 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1044 if (cc_full_descr
->methods
.filter
.input_port_connected
) {
1045 ret
= bt_component_class_filter_set_input_port_connected_method(
1047 cc_full_descr
->methods
.filter
.input_port_connected
);
1049 BT_LIB_LOGE_APPEND_CAUSE(
1050 "Cannot set filter component class's \"input port connected\" method.");
1051 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1052 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1057 if (cc_full_descr
->methods
.filter
.output_port_connected
) {
1058 ret
= bt_component_class_filter_set_output_port_connected_method(
1060 cc_full_descr
->methods
.filter
.output_port_connected
);
1062 BT_LIB_LOGE_APPEND_CAUSE(
1063 "Cannot set filter component class's \"output port connected\" method.");
1064 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1065 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1070 if (cc_full_descr
->methods
.filter
.msg_iter_initialize
) {
1071 ret
= bt_component_class_filter_set_message_iterator_initialize_method(
1073 cc_full_descr
->methods
.filter
.msg_iter_initialize
);
1075 BT_LIB_LOGE_APPEND_CAUSE(
1076 "Cannot set filter component class's message iterator initialization method.");
1077 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1078 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1083 if (cc_full_descr
->methods
.filter
.msg_iter_finalize
) {
1084 ret
= bt_component_class_filter_set_message_iterator_finalize_method(
1086 cc_full_descr
->methods
.filter
.msg_iter_finalize
);
1088 BT_LIB_LOGE_APPEND_CAUSE(
1089 "Cannot set filter component class's message iterator finalization method.");
1090 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1091 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1096 if (cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
) {
1097 ret
= bt_component_class_filter_set_message_iterator_seek_ns_from_origin_methods(
1099 cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
,
1100 cc_full_descr
->methods
.filter
.msg_iter_can_seek_ns_from_origin
);
1102 BT_LIB_LOGE_APPEND_CAUSE(
1103 "Cannot set filter component class's message iterator \"seek nanoseconds from origin\" methods.");
1104 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1105 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1110 if (cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
) {
1111 ret
= bt_component_class_filter_set_message_iterator_seek_beginning_methods(
1113 cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
,
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 \"seek beginning\" methods.");
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
.get_supported_mip_versions
) {
1127 ret
= bt_component_class_sink_set_get_supported_mip_versions_method(
1129 cc_full_descr
->methods
.sink
.get_supported_mip_versions
);
1131 BT_LIB_LOGE_APPEND_CAUSE(
1132 "Cannot set sink component class's \"get supported MIP versions\" 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
.init
) {
1140 ret
= bt_component_class_sink_set_initialize_method(
1142 cc_full_descr
->methods
.sink
.init
);
1144 BT_LIB_LOGE_APPEND_CAUSE(
1145 "Cannot set sink component class's initialization 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
.finalize
) {
1153 ret
= bt_component_class_sink_set_finalize_method(
1155 cc_full_descr
->methods
.sink
.finalize
);
1157 BT_LIB_LOGE_APPEND_CAUSE(
1158 "Cannot set sink component class's finalization 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
.query
) {
1166 ret
= bt_component_class_sink_set_query_method(
1168 cc_full_descr
->methods
.sink
.query
);
1170 BT_LIB_LOGE_APPEND_CAUSE(
1171 "Cannot set sink component class's query 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
.input_port_connected
) {
1179 ret
= bt_component_class_sink_set_input_port_connected_method(
1181 cc_full_descr
->methods
.sink
.input_port_connected
);
1183 BT_LIB_LOGE_APPEND_CAUSE(
1184 "Cannot set sink component class's \"input port connected\" method.");
1185 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1186 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1191 if (cc_full_descr
->methods
.sink
.graph_is_configured
) {
1192 ret
= bt_component_class_sink_set_graph_is_configured_method(
1194 cc_full_descr
->methods
.sink
.graph_is_configured
);
1196 BT_LIB_LOGE_APPEND_CAUSE(
1197 "Cannot set sink component class's \"graph is configured\" method.");
1198 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1199 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1210 * Add component class to the plugin object.
1212 * This will call back
1213 * bt_plugin_so_on_add_component_class() so that we can
1214 * add a mapping in the component class list when we
1215 * know the component class is successfully added.
1217 status
= bt_plugin_add_component_class(plugin
,
1218 (void *) comp_class
);
1219 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
1221 BT_LIB_LOGE_APPEND_CAUSE(
1222 "Cannot add component class to plugin.");
1228 g_array_free(comp_class_full_descriptors
, TRUE
);
1233 struct bt_plugin
*bt_plugin_so_create_empty(
1234 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
)
1236 struct bt_plugin
*plugin
;
1237 struct bt_plugin_so_spec_data
*spec
;
1239 plugin
= bt_plugin_create_empty(BT_PLUGIN_TYPE_SO
);
1244 plugin
->destroy_spec_data
= bt_plugin_so_destroy_spec_data
;
1245 plugin
->spec_data
= g_new0(struct bt_plugin_so_spec_data
, 1);
1246 if (!plugin
->spec_data
) {
1247 BT_LIB_LOGE_APPEND_CAUSE(
1248 "Failed to allocate one SO plugin specific data structure.");
1252 spec
= plugin
->spec_data
;
1253 spec
->shared_lib_handle
= shared_lib_handle
;
1254 bt_object_get_ref_no_null_check(spec
->shared_lib_handle
);
1258 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1265 size_t count_non_null_items_in_section(const void *begin
, const void *end
)
1268 const int * const *begin_int
= (const int * const *) begin
;
1269 const int * const *end_int
= (const int * const *) end
;
1270 const int * const *iter
;
1272 for (iter
= begin_int
; iter
!= end_int
; iter
++) {
1282 int bt_plugin_so_create_all_from_sections(
1283 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
,
1284 bool fail_on_load_error
,
1285 struct __bt_plugin_descriptor
const * const *descriptors_begin
,
1286 struct __bt_plugin_descriptor
const * const *descriptors_end
,
1287 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
1288 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
1289 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
1290 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
1291 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
1292 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
,
1293 struct bt_plugin_set
**plugin_set_out
)
1295 int status
= BT_FUNC_STATUS_OK
;
1296 size_t descriptor_count
;
1298 size_t cc_descriptors_count
;
1299 size_t cc_descr_attrs_count
;
1302 BT_ASSERT(shared_lib_handle
);
1303 BT_ASSERT(plugin_set_out
);
1304 *plugin_set_out
= NULL
;
1305 descriptor_count
= count_non_null_items_in_section(descriptors_begin
, descriptors_end
);
1306 attrs_count
= count_non_null_items_in_section(attrs_begin
, attrs_end
);
1307 cc_descriptors_count
= count_non_null_items_in_section(cc_descriptors_begin
, cc_descriptors_end
);
1308 cc_descr_attrs_count
= count_non_null_items_in_section(cc_descr_attrs_begin
, cc_descr_attrs_end
);
1309 BT_LOGI("Creating all SO plugins from sections: "
1310 "plugin-path=\"%s\", "
1311 "descr-begin-addr=%p, descr-end-addr=%p, "
1312 "attrs-begin-addr=%p, attrs-end-addr=%p, "
1313 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
1314 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p, "
1315 "descr-count=%zu, attrs-count=%zu, "
1316 "cc-descr-count=%zu, cc-descr-attrs-count=%zu",
1317 shared_lib_handle
->path
? shared_lib_handle
->path
->str
: NULL
,
1318 descriptors_begin
, descriptors_end
,
1319 attrs_begin
, attrs_end
,
1320 cc_descriptors_begin
, cc_descriptors_end
,
1321 cc_descr_attrs_begin
, cc_descr_attrs_end
,
1322 descriptor_count
, attrs_count
,
1323 cc_descriptors_count
, cc_descr_attrs_count
);
1324 *plugin_set_out
= bt_plugin_set_create();
1325 if (!*plugin_set_out
) {
1326 BT_LIB_LOGE_APPEND_CAUSE("Cannot create empty plugin set.");
1327 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1331 for (i
= 0; i
< descriptors_end
- descriptors_begin
; i
++) {
1332 const struct __bt_plugin_descriptor
*descriptor
=
1333 descriptors_begin
[i
];
1334 struct bt_plugin
*plugin
;
1340 BT_LOGI("Creating plugin object for plugin: name=\"%s\"",
1342 plugin
= bt_plugin_so_create_empty(shared_lib_handle
);
1344 BT_LIB_LOGE_APPEND_CAUSE(
1345 "Cannot create empty shared library handle.");
1346 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1350 if (shared_lib_handle
->path
) {
1351 bt_plugin_set_path(plugin
,
1352 shared_lib_handle
->path
->str
);
1355 status
= bt_plugin_so_init(plugin
, fail_on_load_error
,
1356 descriptor
, attrs_begin
, attrs_end
,
1357 cc_descriptors_begin
, cc_descriptors_end
,
1358 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1359 if (status
== BT_FUNC_STATUS_OK
) {
1360 /* Add to plugin set */
1361 bt_plugin_set_add_plugin(*plugin_set_out
, plugin
);
1362 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1363 } else if (status
< 0) {
1365 * bt_plugin_so_init() handles
1366 * `fail_on_load_error`, so this is a "real"
1369 BT_LIB_LOGW_APPEND_CAUSE(
1370 "Cannot initialize SO plugin object from sections.");
1371 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1378 BT_ASSERT(*plugin_set_out
);
1380 if ((*plugin_set_out
)->plugins
->len
== 0) {
1381 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out
);
1382 status
= BT_FUNC_STATUS_NOT_FOUND
;
1388 BT_ASSERT(status
< 0);
1389 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out
);
1396 int bt_plugin_so_create_all_from_static(bool fail_on_load_error
,
1397 struct bt_plugin_set
**plugin_set_out
)
1400 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
1402 BT_ASSERT(plugin_set_out
);
1403 *plugin_set_out
= NULL
;
1404 status
= bt_plugin_so_shared_lib_handle_create(NULL
,
1405 &shared_lib_handle
);
1406 if (status
!= BT_FUNC_STATUS_OK
) {
1407 BT_ASSERT(!shared_lib_handle
);
1411 BT_ASSERT(shared_lib_handle
);
1412 BT_LOGD_STR("Creating all SO plugins from built-in plugins.");
1413 status
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
1415 __bt_get_begin_section_plugin_descriptors(),
1416 __bt_get_end_section_plugin_descriptors(),
1417 __bt_get_begin_section_plugin_descriptor_attributes(),
1418 __bt_get_end_section_plugin_descriptor_attributes(),
1419 __bt_get_begin_section_component_class_descriptors(),
1420 __bt_get_end_section_component_class_descriptors(),
1421 __bt_get_begin_section_component_class_descriptor_attributes(),
1422 __bt_get_end_section_component_class_descriptor_attributes(),
1424 BT_ASSERT((status
== BT_FUNC_STATUS_OK
&& *plugin_set_out
&&
1425 (*plugin_set_out
)->plugins
->len
> 0) || !*plugin_set_out
);
1428 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle
);
1433 int bt_plugin_so_create_all_from_file(const char *path
,
1434 bool fail_on_load_error
, struct bt_plugin_set
**plugin_set_out
)
1438 struct __bt_plugin_descriptor
const * const *descriptors_begin
= NULL
;
1439 struct __bt_plugin_descriptor
const * const *descriptors_end
= NULL
;
1440 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
= NULL
;
1441 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
= NULL
;
1442 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
= NULL
;
1443 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
= NULL
;
1444 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
= NULL
;
1445 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
= NULL
;
1446 struct __bt_plugin_descriptor
const * const *(*get_begin_section_plugin_descriptors
)(void);
1447 struct __bt_plugin_descriptor
const * const *(*get_end_section_plugin_descriptors
)(void);
1448 struct __bt_plugin_descriptor_attribute
const * const *(*get_begin_section_plugin_descriptor_attributes
)(void);
1449 struct __bt_plugin_descriptor_attribute
const * const *(*get_end_section_plugin_descriptor_attributes
)(void);
1450 struct __bt_plugin_component_class_descriptor
const * const *(*get_begin_section_component_class_descriptors
)(void);
1451 struct __bt_plugin_component_class_descriptor
const * const *(*get_end_section_component_class_descriptors
)(void);
1452 struct __bt_plugin_component_class_descriptor_attribute
const * const *(*get_begin_section_component_class_descriptor_attributes
)(void);
1453 struct __bt_plugin_component_class_descriptor_attribute
const * const *(*get_end_section_component_class_descriptor_attributes
)(void);
1454 bt_bool is_libtool_wrapper
= BT_FALSE
, is_shared_object
= BT_FALSE
;
1455 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
1458 BT_ASSERT(plugin_set_out
);
1459 *plugin_set_out
= NULL
;
1460 path_len
= strlen(path
);
1463 * An SO plugin file must have a known plugin file suffix. So the file
1464 * path must be longer than the suffix length.
1466 if (path_len
<= PLUGIN_SUFFIX_LEN
) {
1467 BT_LOGI("Path is too short to be an `.so` or `.la` plugin file:"
1468 "path=%s, path-length=%zu, min-length=%zu",
1469 path
, path_len
, PLUGIN_SUFFIX_LEN
);
1470 status
= BT_FUNC_STATUS_NOT_FOUND
;
1474 BT_LOGI("Trying to create all SO plugins from file: path=\"%s\"", path
);
1478 * Check if the file ends with a known plugin file type suffix
1479 * (i.e. .so or .la on Linux).
1481 is_libtool_wrapper
= !strncmp(LIBTOOL_PLUGIN_SUFFIX
,
1482 path
+ path_len
- LIBTOOL_PLUGIN_SUFFIX_LEN
,
1483 LIBTOOL_PLUGIN_SUFFIX_LEN
);
1484 is_shared_object
= !strncmp(NATIVE_PLUGIN_SUFFIX
,
1485 path
+ path_len
- NATIVE_PLUGIN_SUFFIX_LEN
,
1486 NATIVE_PLUGIN_SUFFIX_LEN
);
1487 if (!is_shared_object
&& !is_libtool_wrapper
) {
1488 /* Name indicates this is not a plugin file; not an error */
1489 BT_LOGI("File is not an SO plugin file: path=\"%s\"", path
);
1490 status
= BT_FUNC_STATUS_NOT_FOUND
;
1494 status
= bt_plugin_so_shared_lib_handle_create(path
,
1495 &shared_lib_handle
);
1496 if (status
!= BT_FUNC_STATUS_OK
) {
1497 /* bt_plugin_so_shared_lib_handle_create() logs more details */
1498 BT_ASSERT(!shared_lib_handle
);
1502 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_plugin_descriptors",
1503 (gpointer
*) &get_begin_section_plugin_descriptors
)) {
1504 descriptors_begin
= get_begin_section_plugin_descriptors();
1507 * Use this first symbol to know whether or not this
1508 * shared object _looks like_ a Babeltrace plugin. Since
1509 * g_module_symbol() failed, assume that this is not a
1510 * Babeltrace plugin, so it's not an error.
1512 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1513 "symbol=\"%s\"", path
,
1514 "__bt_get_begin_section_plugin_descriptors");
1515 status
= BT_FUNC_STATUS_NOT_FOUND
;
1520 * If g_module_symbol() fails for any of the other symbols, fail
1521 * if `fail_on_load_error` is true.
1523 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_plugin_descriptors",
1524 (gpointer
*) &get_end_section_plugin_descriptors
)) {
1525 descriptors_end
= get_end_section_plugin_descriptors();
1527 if (fail_on_load_error
) {
1528 BT_LIB_LOGW_APPEND_CAUSE(
1529 "Cannot resolve plugin symbol: path=\"%s\", "
1530 "symbol=\"%s\"", path
,
1531 "__bt_get_end_section_plugin_descriptors");
1532 status
= BT_FUNC_STATUS_ERROR
;
1535 "Cannot resolve plugin symbol: path=\"%s\", "
1536 "symbol=\"%s\"", path
,
1537 "__bt_get_end_section_plugin_descriptors");
1538 status
= BT_FUNC_STATUS_NOT_FOUND
;
1544 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_plugin_descriptor_attributes",
1545 (gpointer
*) &get_begin_section_plugin_descriptor_attributes
)) {
1546 attrs_begin
= get_begin_section_plugin_descriptor_attributes();
1548 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1549 "symbol=\"%s\"", path
,
1550 "__bt_get_begin_section_plugin_descriptor_attributes");
1553 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_plugin_descriptor_attributes",
1554 (gpointer
*) &get_end_section_plugin_descriptor_attributes
)) {
1555 attrs_end
= get_end_section_plugin_descriptor_attributes();
1557 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1558 "symbol=\"%s\"", path
,
1559 "__bt_get_end_section_plugin_descriptor_attributes");
1562 if ((!!attrs_begin
- !!attrs_end
) != 0) {
1563 if (fail_on_load_error
) {
1564 BT_LIB_LOGW_APPEND_CAUSE(
1565 "Found section start or end symbol, but not both: "
1566 "path=\"%s\", symbol-start=\"%s\", "
1567 "symbol-end=\"%s\", symbol-start-addr=%p, "
1568 "symbol-end-addr=%p",
1569 path
, "__bt_get_begin_section_plugin_descriptor_attributes",
1570 "__bt_get_end_section_plugin_descriptor_attributes",
1571 attrs_begin
, attrs_end
);
1572 status
= BT_FUNC_STATUS_ERROR
;
1575 "Found section start or end symbol, but not both: "
1576 "path=\"%s\", symbol-start=\"%s\", "
1577 "symbol-end=\"%s\", symbol-start-addr=%p, "
1578 "symbol-end-addr=%p",
1579 path
, "__bt_get_begin_section_plugin_descriptor_attributes",
1580 "__bt_get_end_section_plugin_descriptor_attributes",
1581 attrs_begin
, attrs_end
);
1582 status
= BT_FUNC_STATUS_NOT_FOUND
;
1588 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_component_class_descriptors",
1589 (gpointer
*) &get_begin_section_component_class_descriptors
)) {
1590 cc_descriptors_begin
= get_begin_section_component_class_descriptors();
1592 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1593 "symbol=\"%s\"", path
,
1594 "__bt_get_begin_section_component_class_descriptors");
1597 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_component_class_descriptors",
1598 (gpointer
*) &get_end_section_component_class_descriptors
)) {
1599 cc_descriptors_end
= get_end_section_component_class_descriptors();
1601 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1602 "symbol=\"%s\"", path
,
1603 "__bt_get_end_section_component_class_descriptors");
1606 if ((!!cc_descriptors_begin
- !!cc_descriptors_end
) != 0) {
1607 if (fail_on_load_error
) {
1608 BT_LIB_LOGW_APPEND_CAUSE(
1609 "Found section start or end symbol, but not both: "
1610 "path=\"%s\", symbol-start=\"%s\", "
1611 "symbol-end=\"%s\", symbol-start-addr=%p, "
1612 "symbol-end-addr=%p",
1613 path
, "__bt_get_begin_section_component_class_descriptors",
1614 "__bt_get_end_section_component_class_descriptors",
1615 cc_descriptors_begin
, cc_descriptors_end
);
1616 status
= BT_FUNC_STATUS_ERROR
;
1619 "Found section start or end symbol, but not both: "
1620 "path=\"%s\", symbol-start=\"%s\", "
1621 "symbol-end=\"%s\", symbol-start-addr=%p, "
1622 "symbol-end-addr=%p",
1623 path
, "__bt_get_begin_section_component_class_descriptors",
1624 "__bt_get_end_section_component_class_descriptors",
1625 cc_descriptors_begin
, cc_descriptors_end
);
1626 status
= BT_FUNC_STATUS_NOT_FOUND
;
1632 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_component_class_descriptor_attributes",
1633 (gpointer
*) &get_begin_section_component_class_descriptor_attributes
)) {
1634 cc_descr_attrs_begin
= get_begin_section_component_class_descriptor_attributes();
1636 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1637 "symbol=\"%s\"", path
,
1638 "__bt_get_begin_section_component_class_descriptor_attributes");
1641 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_component_class_descriptor_attributes",
1642 (gpointer
*) &get_end_section_component_class_descriptor_attributes
)) {
1643 cc_descr_attrs_end
= get_end_section_component_class_descriptor_attributes();
1645 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1646 "symbol=\"%s\"", path
,
1647 "__bt_get_end_section_component_class_descriptor_attributes");
1650 if ((!!cc_descr_attrs_begin
- !!cc_descr_attrs_end
) != 0) {
1651 if (fail_on_load_error
) {
1652 BT_LIB_LOGW_APPEND_CAUSE(
1653 "Found section start or end symbol, but not both: "
1654 "path=\"%s\", symbol-start=\"%s\", "
1655 "symbol-end=\"%s\", symbol-start-addr=%p, "
1656 "symbol-end-addr=%p",
1657 path
, "__bt_get_begin_section_component_class_descriptor_attributes",
1658 "__bt_get_end_section_component_class_descriptor_attributes",
1659 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1660 status
= BT_FUNC_STATUS_ERROR
;
1663 "Found section start or end symbol, but not both: "
1664 "path=\"%s\", symbol-start=\"%s\", "
1665 "symbol-end=\"%s\", symbol-start-addr=%p, "
1666 "symbol-end-addr=%p",
1667 path
, "__bt_get_begin_section_component_class_descriptor_attributes",
1668 "__bt_get_end_section_component_class_descriptor_attributes",
1669 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1670 status
= BT_FUNC_STATUS_NOT_FOUND
;
1676 /* Initialize plugin */
1677 BT_LOGD_STR("Initializing plugin object.");
1678 status
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
1680 descriptors_begin
, descriptors_end
, attrs_begin
, attrs_end
,
1681 cc_descriptors_begin
, cc_descriptors_end
,
1682 cc_descr_attrs_begin
, cc_descr_attrs_end
, plugin_set_out
);
1685 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle
);
1690 void plugin_comp_class_destroy_listener(struct bt_component_class
*comp_class
,
1693 bt_list_del(&comp_class
->node
);
1694 BT_OBJECT_PUT_REF_AND_RESET(comp_class
->so_handle
);
1695 BT_LOGD("Component class destroyed: removed entry from list: "
1696 "comp-cls-addr=%p", comp_class
);
1699 void bt_plugin_so_on_add_component_class(struct bt_plugin
*plugin
,
1700 struct bt_component_class
*comp_class
)
1702 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
1704 BT_ASSERT(plugin
->spec_data
);
1705 BT_ASSERT(plugin
->type
== BT_PLUGIN_TYPE_SO
);
1707 bt_list_add(&comp_class
->node
, &component_class_list
);
1708 comp_class
->so_handle
= spec
->shared_lib_handle
;
1709 bt_object_get_ref_no_null_check(comp_class
->so_handle
);
1711 /* Add our custom destroy listener */
1712 bt_component_class_add_destroy_listener(comp_class
,
1713 plugin_comp_class_destroy_listener
, NULL
);