2 * SPDX-License-Identifier: MIT
4 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
5 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
8 #define BT_LOG_TAG "LIB/PLUGIN-SO"
9 #include "lib/logging.h"
11 #include "common/assert.h"
12 #include "lib/assert-cond.h"
13 #include "compat/compiler.h"
14 #include <babeltrace2/plugin/plugin-dev.h>
15 #include "lib/graph/component-class.h"
16 #include <babeltrace2/graph/component-class.h>
17 #include <babeltrace2/types.h>
18 #include "common/list.h"
26 #include "plugin-so.h"
27 #include "lib/func-status.h"
28 #include "common/common.h"
30 #define NATIVE_PLUGIN_SUFFIX "." G_MODULE_SUFFIX
31 #define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
32 #define LIBTOOL_PLUGIN_SUFFIX ".la"
33 #define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
35 #define PLUGIN_SUFFIX_LEN bt_max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
36 sizeof(LIBTOOL_PLUGIN_SUFFIX))
41 * This list, global to the library, keeps all component classes that
42 * have a reference to their shared library handles. It allows iteration
43 * on all component classes still present when the destructor executes
44 * to release the shared library handle references they might still have.
46 * The list items are the component classes created with
47 * bt_plugin_add_component_class(). They keep the shared library handle
48 * object created by their plugin alive so that the plugin's code is
49 * not discarded when it could still be in use by living components
50 * created from those component classes:
52 * [component] --ref-> [component class]-> [shlib handle]
54 * It allows this use-case:
56 * my_plugins = bt_plugin_find_all_from_file("/path/to/my-plugin.so");
57 * // instantiate components from a plugin's component classes
58 * // put plugins and free my_plugins here
59 * // user code of instantiated components still exists
61 * An entry is removed from this list when a component class is
62 * destroyed thanks to a custom destroy listener. When the entry is
63 * removed, the entry is removed from the list, and we release the
64 * reference on the shlib handle. Assuming the original plugin object
65 * which contained some component classes is put first, when the last
66 * component class is removed from this list, the shared library handle
67 * object's reference count falls to zero and the shared library is
70 * We're not using a GLib linked list here because this destructor is
71 * called after GLib's thread-specific data is destroyed, which contains
72 * the allocated memory for GLib data structures (what's used by
77 BT_LIST_HEAD(component_class_list
);
79 __attribute__((destructor
)) static
80 void fini_comp_class_list(void)
82 struct bt_component_class
*comp_class
, *tmp
;
84 bt_list_for_each_entry_safe(comp_class
, tmp
, &component_class_list
, node
) {
85 bt_list_del(&comp_class
->node
);
86 BT_OBJECT_PUT_REF_AND_RESET(comp_class
->so_handle
);
89 BT_LOGD_STR("Released references from all component classes to shared library handles.");
93 void bt_plugin_so_shared_lib_handle_destroy(struct bt_object
*obj
)
95 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
;
98 shared_lib_handle
= container_of(obj
,
99 struct bt_plugin_so_shared_lib_handle
, base
);
100 const char *path
= shared_lib_handle
->path
?
101 shared_lib_handle
->path
->str
: NULL
;
103 BT_LOGI("Destroying shared library handle: addr=%p, path=\"%s\"",
104 shared_lib_handle
, path
);
106 if (shared_lib_handle
->init_called
&& shared_lib_handle
->exit
) {
107 BT_LOGD_STR("Calling user's plugin exit function.");
108 shared_lib_handle
->exit();
109 BT_LOGD_STR("User function returned.");
112 if (shared_lib_handle
->module
) {
115 * Valgrind shows incomplete stack traces when
116 * dynamically loaded libraries are closed before it
117 * finishes. Use the LIBBABELTRACE2_NO_DLCLOSE in a debug
118 * build to avoid this.
120 const char *var
= getenv("LIBBABELTRACE2_NO_DLCLOSE");
122 if (!var
|| strcmp(var
, "1") != 0) {
124 BT_LOGI("Closing GModule: path=\"%s\"", path
);
126 if (!g_module_close(shared_lib_handle
->module
)) {
128 * Just log here: we're in a destructor,
129 * so we cannot append an error cause
130 * (there's no returned status).
132 BT_LOGE("Cannot close GModule: %s: path=\"%s\"",
133 g_module_error(), path
);
136 shared_lib_handle
->module
= NULL
;
139 BT_LOGI("Not closing GModule because `LIBBABELTRACE2_NO_DLCLOSE=1`: "
140 "path=\"%s\"", path
);
145 if (shared_lib_handle
->path
) {
146 g_string_free(shared_lib_handle
->path
, TRUE
);
147 shared_lib_handle
->path
= NULL
;
150 g_free(shared_lib_handle
);
154 int bt_plugin_so_shared_lib_handle_create(
156 struct bt_plugin_so_shared_lib_handle
**shared_lib_handle
)
158 int status
= BT_FUNC_STATUS_OK
;
160 BT_ASSERT(shared_lib_handle
);
161 BT_LOGI("Creating shared library handle: path=\"%s\"", path
? path
: "(null)");
162 *shared_lib_handle
= g_new0(struct bt_plugin_so_shared_lib_handle
, 1);
163 if (!*shared_lib_handle
) {
164 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one shared library handle.");
165 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
169 bt_object_init_shared(&(*shared_lib_handle
)->base
,
170 bt_plugin_so_shared_lib_handle_destroy
);
176 (*shared_lib_handle
)->path
= g_string_new(path
);
177 if (!(*shared_lib_handle
)->path
) {
178 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
179 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
183 (*shared_lib_handle
)->module
= g_module_open(path
, G_MODULE_BIND_LOCAL
);
184 if (!(*shared_lib_handle
)->module
) {
186 * INFO-level logging because we're only _trying_ to
187 * open this file as a Babeltrace plugin: if it's not,
188 * it's not an error. And because this can be tried
189 * during bt_plugin_find_all_from_dir(), it's not even a
192 BT_LOGI("Cannot open GModule: %s: path=\"%s\"",
193 g_module_error(), path
);
194 BT_OBJECT_PUT_REF_AND_RESET(*shared_lib_handle
);
195 status
= BT_FUNC_STATUS_NOT_FOUND
;
202 BT_ASSERT(*shared_lib_handle
|| status
!= BT_FUNC_STATUS_OK
);
203 if (*shared_lib_handle
) {
204 BT_LOGI("Created shared library handle: path=\"%s\", addr=%p",
205 path
? path
: "(null)", *shared_lib_handle
);
212 void bt_plugin_so_destroy_spec_data(struct bt_plugin
*plugin
)
214 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
216 if (!plugin
->spec_data
) {
220 BT_ASSERT(plugin
->type
== BT_PLUGIN_TYPE_SO
);
222 BT_OBJECT_PUT_REF_AND_RESET(spec
->shared_lib_handle
);
223 g_free(plugin
->spec_data
);
224 plugin
->spec_data
= NULL
;
228 * This function does the following:
230 * 1. Iterate on the plugin descriptor attributes section and set the
231 * plugin's attributes depending on the attribute types. This
232 * includes the name of the plugin, its description, and its
233 * initialization function, for example.
235 * 2. Iterate on the component class descriptors section and create one
236 * "full descriptor" (temporary structure) for each one that is found
237 * and attached to our plugin descriptor.
239 * 3. Iterate on the component class descriptor attributes section and
240 * set the corresponding full descriptor's attributes depending on
241 * the attribute types. This includes the description of the
242 * component class, as well as its initialization and destroy
245 * 4. Call the user's plugin initialization function, if any is
248 * 5. For each full component class descriptor, create a component class
249 * object, set its optional attributes, and add it to the plugin
252 * 6. Freeze the plugin object.
255 int bt_plugin_so_init(struct bt_plugin
*plugin
,
256 bool fail_on_load_error
,
257 const struct __bt_plugin_descriptor
*descriptor
,
258 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
259 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
260 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
261 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
262 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
263 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
)
266 * This structure's members point to the plugin's memory
269 struct comp_class_full_descriptor
{
270 const struct __bt_plugin_component_class_descriptor
*descriptor
;
271 const char *description
;
276 bt_component_class_source_get_supported_mip_versions_method get_supported_mip_versions
;
277 bt_component_class_source_initialize_method init
;
278 bt_component_class_source_finalize_method finalize
;
279 bt_component_class_source_query_method query
;
280 bt_component_class_source_output_port_connected_method output_port_connected
;
281 bt_message_iterator_class_initialize_method msg_iter_initialize
;
282 bt_message_iterator_class_finalize_method msg_iter_finalize
;
283 bt_message_iterator_class_seek_ns_from_origin_method msg_iter_seek_ns_from_origin
;
284 bt_message_iterator_class_seek_beginning_method msg_iter_seek_beginning
;
285 bt_message_iterator_class_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin
;
286 bt_message_iterator_class_can_seek_beginning_method msg_iter_can_seek_beginning
;
290 bt_component_class_filter_get_supported_mip_versions_method get_supported_mip_versions
;
291 bt_component_class_filter_initialize_method init
;
292 bt_component_class_filter_finalize_method finalize
;
293 bt_component_class_filter_query_method query
;
294 bt_component_class_filter_input_port_connected_method input_port_connected
;
295 bt_component_class_filter_output_port_connected_method output_port_connected
;
296 bt_message_iterator_class_initialize_method msg_iter_initialize
;
297 bt_message_iterator_class_finalize_method msg_iter_finalize
;
298 bt_message_iterator_class_seek_ns_from_origin_method msg_iter_seek_ns_from_origin
;
299 bt_message_iterator_class_seek_beginning_method msg_iter_seek_beginning
;
300 bt_message_iterator_class_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin
;
301 bt_message_iterator_class_can_seek_beginning_method msg_iter_can_seek_beginning
;
305 bt_component_class_sink_get_supported_mip_versions_method get_supported_mip_versions
;
306 bt_component_class_sink_initialize_method init
;
307 bt_component_class_sink_finalize_method finalize
;
308 bt_component_class_sink_query_method query
;
309 bt_component_class_sink_input_port_connected_method input_port_connected
;
310 bt_component_class_sink_graph_is_configured_method graph_is_configured
;
315 int status
= BT_FUNC_STATUS_OK
;
316 struct __bt_plugin_descriptor_attribute
const * const *cur_attr_ptr
;
317 struct __bt_plugin_component_class_descriptor
const * const *cur_cc_descr_ptr
;
318 struct __bt_plugin_component_class_descriptor_attribute
const * const *cur_cc_descr_attr_ptr
;
319 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
320 GArray
*comp_class_full_descriptors
;
323 struct bt_message_iterator_class
*msg_iter_class
= NULL
;
325 BT_LOGI("Initializing plugin object from descriptors found in sections: "
326 "plugin-addr=%p, plugin-path=\"%s\", "
327 "attrs-begin-addr=%p, attrs-end-addr=%p, "
328 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
329 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p",
331 spec
->shared_lib_handle
->path
?
332 spec
->shared_lib_handle
->path
->str
: NULL
,
333 attrs_begin
, attrs_end
,
334 cc_descriptors_begin
, cc_descriptors_end
,
335 cc_descr_attrs_begin
, cc_descr_attrs_end
);
336 comp_class_full_descriptors
= g_array_new(FALSE
, TRUE
,
337 sizeof(struct comp_class_full_descriptor
));
338 if (!comp_class_full_descriptors
) {
339 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
340 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
344 /* Set mandatory attributes */
345 spec
->descriptor
= descriptor
;
346 bt_plugin_set_name(plugin
, descriptor
->name
);
349 * Find and set optional attributes attached to this plugin
352 for (cur_attr_ptr
= attrs_begin
; cur_attr_ptr
!= attrs_end
; cur_attr_ptr
++) {
353 const struct __bt_plugin_descriptor_attribute
*cur_attr
=
360 if (cur_attr
->plugin_descriptor
!= descriptor
) {
364 switch (cur_attr
->type
) {
365 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT
:
366 spec
->init
= cur_attr
->value
.init
;
368 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT
:
369 spec
->shared_lib_handle
->exit
= cur_attr
->value
.exit
;
371 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR
:
372 bt_plugin_set_author(plugin
, cur_attr
->value
.author
);
374 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE
:
375 bt_plugin_set_license(plugin
, cur_attr
->value
.license
);
377 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
378 bt_plugin_set_description(plugin
, cur_attr
->value
.description
);
380 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION
:
381 bt_plugin_set_version(plugin
,
382 (unsigned int) cur_attr
->value
.version
.major
,
383 (unsigned int) cur_attr
->value
.version
.minor
,
384 (unsigned int) cur_attr
->value
.version
.patch
,
385 cur_attr
->value
.version
.extra
);
388 if (fail_on_load_error
) {
389 BT_LIB_LOGW_APPEND_CAUSE(
390 "Unknown plugin descriptor attribute: "
391 "plugin-path=\"%s\", plugin-name=\"%s\", "
392 "attr-type-name=\"%s\", attr-type-id=%d",
393 spec
->shared_lib_handle
->path
?
394 spec
->shared_lib_handle
->path
->str
:
396 descriptor
->name
, cur_attr
->type_name
,
398 status
= BT_FUNC_STATUS_ERROR
;
402 "Ignoring unknown plugin descriptor attribute: "
403 "plugin-path=\"%s\", plugin-name=\"%s\", "
404 "attr-type-name=\"%s\", attr-type-id=%d",
405 spec
->shared_lib_handle
->path
?
406 spec
->shared_lib_handle
->path
->str
:
408 descriptor
->name
, cur_attr
->type_name
,
417 * Find component class descriptors attached to this plugin
418 * descriptor and initialize corresponding full component class
419 * descriptors in the array.
421 for (cur_cc_descr_ptr
= cc_descriptors_begin
; cur_cc_descr_ptr
!= cc_descriptors_end
; cur_cc_descr_ptr
++) {
422 const struct __bt_plugin_component_class_descriptor
*cur_cc_descr
=
424 struct comp_class_full_descriptor full_descriptor
= {0};
430 if (cur_cc_descr
->plugin_descriptor
!= descriptor
) {
434 full_descriptor
.descriptor
= cur_cc_descr
;
435 g_array_append_val(comp_class_full_descriptors
,
440 * Find component class descriptor attributes attached to this
441 * plugin descriptor and update corresponding full component
442 * class descriptors in the array.
444 for (cur_cc_descr_attr_ptr
= cc_descr_attrs_begin
; cur_cc_descr_attr_ptr
!= cc_descr_attrs_end
; cur_cc_descr_attr_ptr
++) {
445 const struct __bt_plugin_component_class_descriptor_attribute
*cur_cc_descr_attr
=
446 *cur_cc_descr_attr_ptr
;
447 enum bt_component_class_type cc_type
;
449 if (!cur_cc_descr_attr
) {
453 if (cur_cc_descr_attr
->comp_class_descriptor
->plugin_descriptor
!=
458 cc_type
= cur_cc_descr_attr
->comp_class_descriptor
->type
;
460 /* Find the corresponding component class descriptor entry */
461 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
462 struct comp_class_full_descriptor
*cc_full_descr
=
463 &g_array_index(comp_class_full_descriptors
,
464 struct comp_class_full_descriptor
, i
);
466 if (cur_cc_descr_attr
->comp_class_descriptor
!=
467 cc_full_descr
->descriptor
) {
471 switch (cur_cc_descr_attr
->type
) {
472 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
473 cc_full_descr
->description
=
474 cur_cc_descr_attr
->value
.description
;
476 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP
:
477 cc_full_descr
->help
=
478 cur_cc_descr_attr
->value
.help
;
480 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GET_SUPPORTED_MIP_VERSIONS_METHOD
:
482 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
483 cc_full_descr
->methods
.source
.get_supported_mip_versions
=
484 cur_cc_descr_attr
->value
.source_get_supported_mip_versions_method
;
486 case BT_COMPONENT_CLASS_TYPE_FILTER
:
487 cc_full_descr
->methods
.filter
.get_supported_mip_versions
=
488 cur_cc_descr_attr
->value
.filter_get_supported_mip_versions_method
;
490 case BT_COMPONENT_CLASS_TYPE_SINK
:
491 cc_full_descr
->methods
.sink
.get_supported_mip_versions
=
492 cur_cc_descr_attr
->value
.sink_get_supported_mip_versions_method
;
498 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INITIALIZE_METHOD
:
500 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
501 cc_full_descr
->methods
.source
.init
=
502 cur_cc_descr_attr
->value
.source_initialize_method
;
504 case BT_COMPONENT_CLASS_TYPE_FILTER
:
505 cc_full_descr
->methods
.filter
.init
=
506 cur_cc_descr_attr
->value
.filter_initialize_method
;
508 case BT_COMPONENT_CLASS_TYPE_SINK
:
509 cc_full_descr
->methods
.sink
.init
=
510 cur_cc_descr_attr
->value
.sink_initialize_method
;
516 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD
:
518 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
519 cc_full_descr
->methods
.source
.finalize
=
520 cur_cc_descr_attr
->value
.source_finalize_method
;
522 case BT_COMPONENT_CLASS_TYPE_FILTER
:
523 cc_full_descr
->methods
.filter
.finalize
=
524 cur_cc_descr_attr
->value
.filter_finalize_method
;
526 case BT_COMPONENT_CLASS_TYPE_SINK
:
527 cc_full_descr
->methods
.sink
.finalize
=
528 cur_cc_descr_attr
->value
.sink_finalize_method
;
534 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD
:
536 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
537 cc_full_descr
->methods
.source
.query
=
538 cur_cc_descr_attr
->value
.source_query_method
;
540 case BT_COMPONENT_CLASS_TYPE_FILTER
:
541 cc_full_descr
->methods
.filter
.query
=
542 cur_cc_descr_attr
->value
.filter_query_method
;
544 case BT_COMPONENT_CLASS_TYPE_SINK
:
545 cc_full_descr
->methods
.sink
.query
=
546 cur_cc_descr_attr
->value
.sink_query_method
;
552 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INPUT_PORT_CONNECTED_METHOD
:
554 case BT_COMPONENT_CLASS_TYPE_FILTER
:
555 cc_full_descr
->methods
.filter
.input_port_connected
=
556 cur_cc_descr_attr
->value
.filter_input_port_connected_method
;
558 case BT_COMPONENT_CLASS_TYPE_SINK
:
559 cc_full_descr
->methods
.sink
.input_port_connected
=
560 cur_cc_descr_attr
->value
.sink_input_port_connected_method
;
566 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_OUTPUT_PORT_CONNECTED_METHOD
:
568 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
569 cc_full_descr
->methods
.source
.output_port_connected
=
570 cur_cc_descr_attr
->value
.source_output_port_connected_method
;
572 case BT_COMPONENT_CLASS_TYPE_FILTER
:
573 cc_full_descr
->methods
.filter
.output_port_connected
=
574 cur_cc_descr_attr
->value
.filter_output_port_connected_method
;
580 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GRAPH_IS_CONFIGURED_METHOD
:
582 case BT_COMPONENT_CLASS_TYPE_SINK
:
583 cc_full_descr
->methods
.sink
.graph_is_configured
=
584 cur_cc_descr_attr
->value
.sink_graph_is_configured_method
;
590 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_INITIALIZE_METHOD
:
592 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
593 cc_full_descr
->methods
.source
.msg_iter_initialize
=
594 cur_cc_descr_attr
->value
.msg_iter_initialize_method
;
596 case BT_COMPONENT_CLASS_TYPE_FILTER
:
597 cc_full_descr
->methods
.filter
.msg_iter_initialize
=
598 cur_cc_descr_attr
->value
.msg_iter_initialize_method
;
604 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_FINALIZE_METHOD
:
606 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
607 cc_full_descr
->methods
.source
.msg_iter_finalize
=
608 cur_cc_descr_attr
->value
.msg_iter_finalize_method
;
610 case BT_COMPONENT_CLASS_TYPE_FILTER
:
611 cc_full_descr
->methods
.filter
.msg_iter_finalize
=
612 cur_cc_descr_attr
->value
.msg_iter_finalize_method
;
618 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_NS_FROM_ORIGIN_METHOD
:
620 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
621 cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
=
622 cur_cc_descr_attr
->value
.msg_iter_seek_ns_from_origin_method
;
624 case BT_COMPONENT_CLASS_TYPE_FILTER
:
625 cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
=
626 cur_cc_descr_attr
->value
.msg_iter_seek_ns_from_origin_method
;
632 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_BEGINNING_METHOD
:
634 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
635 cc_full_descr
->methods
.source
.msg_iter_seek_beginning
=
636 cur_cc_descr_attr
->value
.msg_iter_seek_beginning_method
;
638 case BT_COMPONENT_CLASS_TYPE_FILTER
:
639 cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
=
640 cur_cc_descr_attr
->value
.msg_iter_seek_beginning_method
;
646 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_NS_FROM_ORIGIN_METHOD
:
648 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
649 cc_full_descr
->methods
.source
.msg_iter_can_seek_ns_from_origin
=
650 cur_cc_descr_attr
->value
.msg_iter_can_seek_ns_from_origin_method
;
652 case BT_COMPONENT_CLASS_TYPE_FILTER
:
653 cc_full_descr
->methods
.filter
.msg_iter_can_seek_ns_from_origin
=
654 cur_cc_descr_attr
->value
.msg_iter_can_seek_ns_from_origin_method
;
660 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_BEGINNING_METHOD
:
662 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
663 cc_full_descr
->methods
.source
.msg_iter_can_seek_beginning
=
664 cur_cc_descr_attr
->value
.msg_iter_can_seek_beginning_method
;
666 case BT_COMPONENT_CLASS_TYPE_FILTER
:
667 cc_full_descr
->methods
.filter
.msg_iter_can_seek_beginning
=
668 cur_cc_descr_attr
->value
.msg_iter_can_seek_beginning_method
;
675 if (fail_on_load_error
) {
676 BT_LIB_LOGW_APPEND_CAUSE(
677 "Unknown component class descriptor attribute: "
678 "plugin-path=\"%s\", "
679 "plugin-name=\"%s\", "
680 "comp-class-name=\"%s\", "
681 "comp-class-type=%s, "
682 "attr-type-name=\"%s\", "
684 spec
->shared_lib_handle
->path
?
685 spec
->shared_lib_handle
->path
->str
:
688 cur_cc_descr_attr
->comp_class_descriptor
->name
,
689 bt_component_class_type_string(
690 cur_cc_descr_attr
->comp_class_descriptor
->type
),
691 cur_cc_descr_attr
->type_name
,
692 cur_cc_descr_attr
->type
);
693 status
= BT_FUNC_STATUS_ERROR
;
697 "Ignoring unknown component class descriptor attribute: "
698 "plugin-path=\"%s\", "
699 "plugin-name=\"%s\", "
700 "comp-class-name=\"%s\", "
701 "comp-class-type=%s, "
702 "attr-type-name=\"%s\", "
704 spec
->shared_lib_handle
->path
?
705 spec
->shared_lib_handle
->path
->str
:
708 cur_cc_descr_attr
->comp_class_descriptor
->name
,
709 bt_component_class_type_string(
710 cur_cc_descr_attr
->comp_class_descriptor
->type
),
711 cur_cc_descr_attr
->type_name
,
712 cur_cc_descr_attr
->type
);
720 /* Initialize plugin */
722 enum bt_plugin_initialize_func_status init_status
;
724 BT_LOGD_STR("Calling user's plugin initialization function.");
725 init_status
= spec
->init((void *) plugin
);
726 BT_LOGD("User function returned: status=%s",
727 bt_common_func_status_string(init_status
));
729 if (init_status
< 0) {
730 if (fail_on_load_error
) {
731 BT_LIB_LOGW_APPEND_CAUSE(
732 "User's plugin initialization function failed: "
734 bt_common_func_status_string(init_status
));
735 status
= init_status
;
739 "User's plugin initialization function failed: "
741 bt_common_func_status_string(init_status
));
742 status
= BT_FUNC_STATUS_NOT_FOUND
;
749 spec
->shared_lib_handle
->init_called
= BT_TRUE
;
751 /* Add described component classes to plugin */
752 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
753 struct comp_class_full_descriptor
*cc_full_descr
=
754 &g_array_index(comp_class_full_descriptors
,
755 struct comp_class_full_descriptor
, i
);
756 struct bt_component_class
*comp_class
= NULL
;
757 struct bt_component_class_source
*src_comp_class
= NULL
;
758 struct bt_component_class_filter
*flt_comp_class
= NULL
;
759 struct bt_component_class_sink
*sink_comp_class
= NULL
;
761 BT_LOGI("Creating and setting properties of plugin's component class: "
762 "plugin-path=\"%s\", plugin-name=\"%s\", "
763 "comp-class-name=\"%s\", comp-class-type=%s",
764 spec
->shared_lib_handle
->path
?
765 spec
->shared_lib_handle
->path
->str
:
768 cc_full_descr
->descriptor
->name
,
769 bt_component_class_type_string(
770 cc_full_descr
->descriptor
->type
));
772 if (cc_full_descr
->descriptor
->type
== BT_COMPONENT_CLASS_TYPE_SOURCE
||
773 cc_full_descr
->descriptor
->type
== BT_COMPONENT_CLASS_TYPE_FILTER
) {
774 bt_message_iterator_class_next_method next_method
;
775 bt_message_iterator_class_initialize_method init_method
;
776 bt_message_iterator_class_finalize_method fini_method
;
777 bt_message_iterator_class_seek_ns_from_origin_method seek_ns_from_origin_method
;
778 bt_message_iterator_class_seek_beginning_method seek_beginning_method
;
779 bt_message_iterator_class_can_seek_ns_from_origin_method can_seek_ns_from_origin_method
;
780 bt_message_iterator_class_can_seek_beginning_method can_seek_beginning_method
;
782 if (cc_full_descr
->descriptor
->type
== BT_COMPONENT_CLASS_TYPE_SOURCE
) {
783 next_method
= cc_full_descr
->descriptor
->methods
.source
.msg_iter_next
;
784 init_method
= cc_full_descr
->methods
.source
.msg_iter_initialize
;
785 fini_method
= cc_full_descr
->methods
.source
.msg_iter_finalize
;
786 seek_ns_from_origin_method
= cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
;
787 can_seek_ns_from_origin_method
= cc_full_descr
->methods
.source
.msg_iter_can_seek_ns_from_origin
;
788 seek_beginning_method
= cc_full_descr
->methods
.source
.msg_iter_seek_beginning
;
789 can_seek_beginning_method
= cc_full_descr
->methods
.source
.msg_iter_can_seek_beginning
;
791 next_method
= cc_full_descr
->descriptor
->methods
.filter
.msg_iter_next
;
792 init_method
= cc_full_descr
->methods
.filter
.msg_iter_initialize
;
793 fini_method
= cc_full_descr
->methods
.filter
.msg_iter_finalize
;
794 seek_ns_from_origin_method
= cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
;
795 can_seek_ns_from_origin_method
= cc_full_descr
->methods
.filter
.msg_iter_can_seek_ns_from_origin
;
796 seek_beginning_method
= cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
;
797 can_seek_beginning_method
= cc_full_descr
->methods
.filter
.msg_iter_can_seek_beginning
;
800 msg_iter_class
= bt_message_iterator_class_create(next_method
);
801 if (!msg_iter_class
) {
802 BT_LIB_LOGE_APPEND_CAUSE(
803 "Cannot create message iterator class.");
804 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
809 ret
= bt_message_iterator_class_set_initialize_method(
810 msg_iter_class
, init_method
);
812 BT_LIB_LOGE_APPEND_CAUSE(
813 "Cannot set message iterator initialization method.");
814 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
820 ret
= bt_message_iterator_class_set_finalize_method(
821 msg_iter_class
, fini_method
);
823 BT_LIB_LOGE_APPEND_CAUSE(
824 "Cannot set message iterator finalization method.");
825 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
830 if (seek_ns_from_origin_method
) {
831 ret
= bt_message_iterator_class_set_seek_ns_from_origin_methods(
833 seek_ns_from_origin_method
,
834 can_seek_ns_from_origin_method
);
836 BT_LIB_LOGE_APPEND_CAUSE(
837 "Cannot set message iterator \"seek nanoseconds from origin\" methods.");
838 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
843 if (seek_beginning_method
) {
844 ret
= bt_message_iterator_class_set_seek_beginning_methods(
846 seek_beginning_method
,
847 can_seek_beginning_method
);
849 BT_LIB_LOGE_APPEND_CAUSE(
850 "Cannot set message iterator \"seek beginning\" methods.");
851 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
857 switch (cc_full_descr
->descriptor
->type
) {
858 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
859 BT_ASSERT(msg_iter_class
);
861 src_comp_class
= bt_component_class_source_create(
862 cc_full_descr
->descriptor
->name
, msg_iter_class
);
863 comp_class
= bt_component_class_source_as_component_class(
866 case BT_COMPONENT_CLASS_TYPE_FILTER
:
867 BT_ASSERT(msg_iter_class
);
869 flt_comp_class
= bt_component_class_filter_create(
870 cc_full_descr
->descriptor
->name
, msg_iter_class
);
871 comp_class
= bt_component_class_filter_as_component_class(
874 case BT_COMPONENT_CLASS_TYPE_SINK
:
875 BT_ASSERT(!msg_iter_class
);
877 sink_comp_class
= bt_component_class_sink_create(
878 cc_full_descr
->descriptor
->name
,
879 cc_full_descr
->descriptor
->methods
.sink
.consume
);
880 comp_class
= bt_component_class_sink_as_component_class(
884 if (fail_on_load_error
) {
885 BT_LIB_LOGW_APPEND_CAUSE(
886 "Unknown component class type: "
887 "plugin-path=\"%s\", plugin-name=\"%s\", "
888 "comp-class-name=\"%s\", comp-class-type=%d",
889 spec
->shared_lib_handle
->path
->str
?
890 spec
->shared_lib_handle
->path
->str
:
893 cc_full_descr
->descriptor
->name
,
894 cc_full_descr
->descriptor
->type
);
895 status
= BT_FUNC_STATUS_ERROR
;
899 "Ignoring unknown component class type: "
900 "plugin-path=\"%s\", plugin-name=\"%s\", "
901 "comp-class-name=\"%s\", comp-class-type=%d",
902 spec
->shared_lib_handle
->path
->str
?
903 spec
->shared_lib_handle
->path
->str
:
906 cc_full_descr
->descriptor
->name
,
907 cc_full_descr
->descriptor
->type
);
913 BT_LIB_LOGE_APPEND_CAUSE(
914 "Cannot create component class.");
915 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
920 * The component class has taken a reference on the message
921 * iterator class, so we can drop ours. The message iterator
922 * class will get destroyed at the same time as the component
925 bt_message_iterator_class_put_ref(msg_iter_class
);
926 msg_iter_class
= NULL
;
928 if (cc_full_descr
->description
) {
929 ret
= bt_component_class_set_description(
930 comp_class
, cc_full_descr
->description
);
932 BT_LIB_LOGE_APPEND_CAUSE(
933 "Cannot set component class's description.");
934 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
935 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
940 if (cc_full_descr
->help
) {
941 ret
= bt_component_class_set_help(comp_class
,
942 cc_full_descr
->help
);
944 BT_LIB_LOGE_APPEND_CAUSE(
945 "Cannot set component class's help string.");
946 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
947 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
952 switch (cc_full_descr
->descriptor
->type
) {
953 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
954 if (cc_full_descr
->methods
.source
.get_supported_mip_versions
) {
955 ret
= bt_component_class_source_set_get_supported_mip_versions_method(
957 cc_full_descr
->methods
.source
.get_supported_mip_versions
);
959 BT_LIB_LOGE_APPEND_CAUSE(
960 "Cannot set source component class's \"get supported MIP versions\" method.");
961 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
962 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
967 if (cc_full_descr
->methods
.source
.init
) {
968 ret
= bt_component_class_source_set_initialize_method(
970 cc_full_descr
->methods
.source
.init
);
972 BT_LIB_LOGE_APPEND_CAUSE(
973 "Cannot set source component class's initialization method.");
974 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
975 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
980 if (cc_full_descr
->methods
.source
.finalize
) {
981 ret
= bt_component_class_source_set_finalize_method(
983 cc_full_descr
->methods
.source
.finalize
);
985 BT_LIB_LOGE_APPEND_CAUSE(
986 "Cannot set source component class's finalization method.");
987 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
988 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
993 if (cc_full_descr
->methods
.source
.query
) {
994 ret
= bt_component_class_source_set_query_method(
996 cc_full_descr
->methods
.source
.query
);
998 BT_LIB_LOGE_APPEND_CAUSE(
999 "Cannot set source component class's query method.");
1000 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1001 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
1006 if (cc_full_descr
->methods
.source
.output_port_connected
) {
1007 ret
= bt_component_class_source_set_output_port_connected_method(
1009 cc_full_descr
->methods
.source
.output_port_connected
);
1011 BT_LIB_LOGE_APPEND_CAUSE(
1012 "Cannot set source component class's \"output port connected\" method.");
1013 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1014 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
1020 case BT_COMPONENT_CLASS_TYPE_FILTER
:
1021 if (cc_full_descr
->methods
.filter
.get_supported_mip_versions
) {
1022 ret
= bt_component_class_filter_set_get_supported_mip_versions_method(
1024 cc_full_descr
->methods
.filter
.get_supported_mip_versions
);
1026 BT_LIB_LOGE_APPEND_CAUSE(
1027 "Cannot set filter component class's \"get supported MIP versions\" method.");
1028 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1029 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1034 if (cc_full_descr
->methods
.filter
.init
) {
1035 ret
= bt_component_class_filter_set_initialize_method(
1037 cc_full_descr
->methods
.filter
.init
);
1039 BT_LIB_LOGE_APPEND_CAUSE(
1040 "Cannot set filter component class's initialization method.");
1041 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1042 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1047 if (cc_full_descr
->methods
.filter
.finalize
) {
1048 ret
= bt_component_class_filter_set_finalize_method(
1050 cc_full_descr
->methods
.filter
.finalize
);
1052 BT_LIB_LOGE_APPEND_CAUSE(
1053 "Cannot set filter component class's finalization method.");
1054 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1055 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1060 if (cc_full_descr
->methods
.filter
.query
) {
1061 ret
= bt_component_class_filter_set_query_method(
1063 cc_full_descr
->methods
.filter
.query
);
1065 BT_LIB_LOGE_APPEND_CAUSE(
1066 "Cannot set filter component class's query method.");
1067 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1068 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1073 if (cc_full_descr
->methods
.filter
.input_port_connected
) {
1074 ret
= bt_component_class_filter_set_input_port_connected_method(
1076 cc_full_descr
->methods
.filter
.input_port_connected
);
1078 BT_LIB_LOGE_APPEND_CAUSE(
1079 "Cannot set filter component class's \"input port connected\" method.");
1080 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1081 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1086 if (cc_full_descr
->methods
.filter
.output_port_connected
) {
1087 ret
= bt_component_class_filter_set_output_port_connected_method(
1089 cc_full_descr
->methods
.filter
.output_port_connected
);
1091 BT_LIB_LOGE_APPEND_CAUSE(
1092 "Cannot set filter component class's \"output port connected\" method.");
1093 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1094 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1100 case BT_COMPONENT_CLASS_TYPE_SINK
:
1101 if (cc_full_descr
->methods
.sink
.get_supported_mip_versions
) {
1102 ret
= bt_component_class_sink_set_get_supported_mip_versions_method(
1104 cc_full_descr
->methods
.sink
.get_supported_mip_versions
);
1106 BT_LIB_LOGE_APPEND_CAUSE(
1107 "Cannot set sink component class's \"get supported MIP versions\" method.");
1108 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1109 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1114 if (cc_full_descr
->methods
.sink
.init
) {
1115 ret
= bt_component_class_sink_set_initialize_method(
1117 cc_full_descr
->methods
.sink
.init
);
1119 BT_LIB_LOGE_APPEND_CAUSE(
1120 "Cannot set sink component class's initialization method.");
1121 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1122 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1127 if (cc_full_descr
->methods
.sink
.finalize
) {
1128 ret
= bt_component_class_sink_set_finalize_method(
1130 cc_full_descr
->methods
.sink
.finalize
);
1132 BT_LIB_LOGE_APPEND_CAUSE(
1133 "Cannot set sink component class's finalization method.");
1134 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1135 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1140 if (cc_full_descr
->methods
.sink
.query
) {
1141 ret
= bt_component_class_sink_set_query_method(
1143 cc_full_descr
->methods
.sink
.query
);
1145 BT_LIB_LOGE_APPEND_CAUSE(
1146 "Cannot set sink component class's query method.");
1147 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1148 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1153 if (cc_full_descr
->methods
.sink
.input_port_connected
) {
1154 ret
= bt_component_class_sink_set_input_port_connected_method(
1156 cc_full_descr
->methods
.sink
.input_port_connected
);
1158 BT_LIB_LOGE_APPEND_CAUSE(
1159 "Cannot set sink component class's \"input port connected\" method.");
1160 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1161 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1166 if (cc_full_descr
->methods
.sink
.graph_is_configured
) {
1167 ret
= bt_component_class_sink_set_graph_is_configured_method(
1169 cc_full_descr
->methods
.sink
.graph_is_configured
);
1171 BT_LIB_LOGE_APPEND_CAUSE(
1172 "Cannot set sink component class's \"graph is configured\" method.");
1173 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1174 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1185 * Add component class to the plugin object.
1187 * This will call back
1188 * bt_plugin_so_on_add_component_class() so that we can
1189 * add a mapping in the component class list when we
1190 * know the component class is successfully added.
1192 status
= bt_plugin_add_component_class(plugin
,
1193 (void *) comp_class
);
1194 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
1196 BT_LIB_LOGE_APPEND_CAUSE(
1197 "Cannot add component class to plugin.");
1203 bt_message_iterator_class_put_ref(msg_iter_class
);
1204 g_array_free(comp_class_full_descriptors
, TRUE
);
1209 struct bt_plugin
*bt_plugin_so_create_empty(
1210 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
)
1212 struct bt_plugin
*plugin
;
1213 struct bt_plugin_so_spec_data
*spec
;
1215 plugin
= bt_plugin_create_empty(BT_PLUGIN_TYPE_SO
);
1220 plugin
->destroy_spec_data
= bt_plugin_so_destroy_spec_data
;
1221 plugin
->spec_data
= g_new0(struct bt_plugin_so_spec_data
, 1);
1222 if (!plugin
->spec_data
) {
1223 BT_LIB_LOGE_APPEND_CAUSE(
1224 "Failed to allocate one SO plugin specific data structure.");
1228 spec
= plugin
->spec_data
;
1229 spec
->shared_lib_handle
= shared_lib_handle
;
1230 bt_object_get_ref_no_null_check(spec
->shared_lib_handle
);
1234 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1241 size_t count_non_null_items_in_section(const void *begin
, const void *end
)
1244 const int * const *begin_int
= (const int * const *) begin
;
1245 const int * const *end_int
= (const int * const *) end
;
1246 const int * const *iter
;
1248 for (iter
= begin_int
; iter
!= end_int
; iter
++) {
1258 int bt_plugin_so_create_all_from_sections(
1259 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
,
1260 bool fail_on_load_error
,
1261 struct __bt_plugin_descriptor
const * const *descriptors_begin
,
1262 struct __bt_plugin_descriptor
const * const *descriptors_end
,
1263 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
1264 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
1265 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
1266 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
1267 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
1268 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
,
1269 struct bt_plugin_set
**plugin_set_out
)
1271 int status
= BT_FUNC_STATUS_OK
;
1272 size_t descriptor_count
;
1274 size_t cc_descriptors_count
;
1275 size_t cc_descr_attrs_count
;
1278 BT_ASSERT(shared_lib_handle
);
1279 BT_ASSERT(plugin_set_out
);
1280 *plugin_set_out
= NULL
;
1281 descriptor_count
= count_non_null_items_in_section(descriptors_begin
, descriptors_end
);
1282 attrs_count
= count_non_null_items_in_section(attrs_begin
, attrs_end
);
1283 cc_descriptors_count
= count_non_null_items_in_section(cc_descriptors_begin
, cc_descriptors_end
);
1284 cc_descr_attrs_count
= count_non_null_items_in_section(cc_descr_attrs_begin
, cc_descr_attrs_end
);
1285 BT_LOGI("Creating all SO plugins from sections: "
1286 "plugin-path=\"%s\", "
1287 "descr-begin-addr=%p, descr-end-addr=%p, "
1288 "attrs-begin-addr=%p, attrs-end-addr=%p, "
1289 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
1290 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p, "
1291 "descr-count=%zu, attrs-count=%zu, "
1292 "cc-descr-count=%zu, cc-descr-attrs-count=%zu",
1293 shared_lib_handle
->path
? shared_lib_handle
->path
->str
: NULL
,
1294 descriptors_begin
, descriptors_end
,
1295 attrs_begin
, attrs_end
,
1296 cc_descriptors_begin
, cc_descriptors_end
,
1297 cc_descr_attrs_begin
, cc_descr_attrs_end
,
1298 descriptor_count
, attrs_count
,
1299 cc_descriptors_count
, cc_descr_attrs_count
);
1300 *plugin_set_out
= bt_plugin_set_create();
1301 if (!*plugin_set_out
) {
1302 BT_LIB_LOGE_APPEND_CAUSE("Cannot create empty plugin set.");
1303 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1307 for (i
= 0; i
< descriptors_end
- descriptors_begin
; i
++) {
1308 const struct __bt_plugin_descriptor
*descriptor
=
1309 descriptors_begin
[i
];
1310 struct bt_plugin
*plugin
;
1316 BT_LOGI("Creating plugin object for plugin: name=\"%s\"",
1318 plugin
= bt_plugin_so_create_empty(shared_lib_handle
);
1320 BT_LIB_LOGE_APPEND_CAUSE(
1321 "Cannot create empty shared library handle.");
1322 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1326 if (shared_lib_handle
->path
) {
1327 bt_plugin_set_path(plugin
,
1328 shared_lib_handle
->path
->str
);
1331 status
= bt_plugin_so_init(plugin
, fail_on_load_error
,
1332 descriptor
, attrs_begin
, attrs_end
,
1333 cc_descriptors_begin
, cc_descriptors_end
,
1334 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1335 if (status
== BT_FUNC_STATUS_OK
) {
1336 /* Add to plugin set */
1337 bt_plugin_set_add_plugin(*plugin_set_out
, plugin
);
1338 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1339 } else if (status
< 0) {
1341 * bt_plugin_so_init() handles
1342 * `fail_on_load_error`, so this is a "real"
1345 BT_LIB_LOGW_APPEND_CAUSE(
1346 "Cannot initialize SO plugin object from sections.");
1347 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1354 BT_ASSERT(*plugin_set_out
);
1356 if ((*plugin_set_out
)->plugins
->len
== 0) {
1357 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out
);
1358 status
= BT_FUNC_STATUS_NOT_FOUND
;
1364 BT_ASSERT(status
< 0);
1365 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out
);
1372 int bt_plugin_so_create_all_from_static(bool fail_on_load_error
,
1373 struct bt_plugin_set
**plugin_set_out
)
1376 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
1378 BT_ASSERT(plugin_set_out
);
1379 *plugin_set_out
= NULL
;
1380 status
= bt_plugin_so_shared_lib_handle_create(NULL
,
1381 &shared_lib_handle
);
1382 if (status
!= BT_FUNC_STATUS_OK
) {
1383 BT_ASSERT(!shared_lib_handle
);
1387 BT_ASSERT(shared_lib_handle
);
1388 BT_LOGD_STR("Creating all SO plugins from built-in plugins.");
1389 status
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
1391 __bt_get_begin_section_plugin_descriptors(),
1392 __bt_get_end_section_plugin_descriptors(),
1393 __bt_get_begin_section_plugin_descriptor_attributes(),
1394 __bt_get_end_section_plugin_descriptor_attributes(),
1395 __bt_get_begin_section_component_class_descriptors(),
1396 __bt_get_end_section_component_class_descriptors(),
1397 __bt_get_begin_section_component_class_descriptor_attributes(),
1398 __bt_get_end_section_component_class_descriptor_attributes(),
1400 BT_ASSERT((status
== BT_FUNC_STATUS_OK
&& *plugin_set_out
&&
1401 (*plugin_set_out
)->plugins
->len
> 0) || !*plugin_set_out
);
1404 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle
);
1409 int bt_plugin_so_create_all_from_file(const char *path
,
1410 bool fail_on_load_error
, struct bt_plugin_set
**plugin_set_out
)
1414 struct __bt_plugin_descriptor
const * const *descriptors_begin
= NULL
;
1415 struct __bt_plugin_descriptor
const * const *descriptors_end
= NULL
;
1416 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
= NULL
;
1417 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
= NULL
;
1418 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
= NULL
;
1419 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
= NULL
;
1420 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
= NULL
;
1421 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
= NULL
;
1422 struct __bt_plugin_descriptor
const * const *(*get_begin_section_plugin_descriptors
)(void);
1423 struct __bt_plugin_descriptor
const * const *(*get_end_section_plugin_descriptors
)(void);
1424 struct __bt_plugin_descriptor_attribute
const * const *(*get_begin_section_plugin_descriptor_attributes
)(void);
1425 struct __bt_plugin_descriptor_attribute
const * const *(*get_end_section_plugin_descriptor_attributes
)(void);
1426 struct __bt_plugin_component_class_descriptor
const * const *(*get_begin_section_component_class_descriptors
)(void);
1427 struct __bt_plugin_component_class_descriptor
const * const *(*get_end_section_component_class_descriptors
)(void);
1428 struct __bt_plugin_component_class_descriptor_attribute
const * const *(*get_begin_section_component_class_descriptor_attributes
)(void);
1429 struct __bt_plugin_component_class_descriptor_attribute
const * const *(*get_end_section_component_class_descriptor_attributes
)(void);
1430 bt_bool is_libtool_wrapper
= BT_FALSE
, is_shared_object
= BT_FALSE
;
1431 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
1434 BT_ASSERT(plugin_set_out
);
1435 *plugin_set_out
= NULL
;
1436 path_len
= strlen(path
);
1439 * An SO plugin file must have a known plugin file suffix. So the file
1440 * path must be longer than the suffix length.
1442 if (path_len
<= PLUGIN_SUFFIX_LEN
) {
1443 BT_LOGI("Path is too short to be an `.so` or `.la` plugin file:"
1444 "path=%s, path-length=%zu, min-length=%zu",
1445 path
, path_len
, PLUGIN_SUFFIX_LEN
);
1446 status
= BT_FUNC_STATUS_NOT_FOUND
;
1450 BT_LOGI("Trying to create all SO plugins from file: path=\"%s\"", path
);
1454 * Check if the file ends with a known plugin file type suffix
1455 * (i.e. .so or .la on Linux).
1457 is_libtool_wrapper
= !strncmp(LIBTOOL_PLUGIN_SUFFIX
,
1458 path
+ path_len
- LIBTOOL_PLUGIN_SUFFIX_LEN
,
1459 LIBTOOL_PLUGIN_SUFFIX_LEN
);
1460 is_shared_object
= !strncmp(NATIVE_PLUGIN_SUFFIX
,
1461 path
+ path_len
- NATIVE_PLUGIN_SUFFIX_LEN
,
1462 NATIVE_PLUGIN_SUFFIX_LEN
);
1463 if (!is_shared_object
&& !is_libtool_wrapper
) {
1464 /* Name indicates this is not a plugin file; not an error */
1465 BT_LOGI("File is not an SO plugin file: path=\"%s\"", path
);
1466 status
= BT_FUNC_STATUS_NOT_FOUND
;
1470 status
= bt_plugin_so_shared_lib_handle_create(path
,
1471 &shared_lib_handle
);
1472 if (status
!= BT_FUNC_STATUS_OK
) {
1473 /* bt_plugin_so_shared_lib_handle_create() logs more details */
1474 BT_ASSERT(!shared_lib_handle
);
1478 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_plugin_descriptors",
1479 (gpointer
*) &get_begin_section_plugin_descriptors
)) {
1480 descriptors_begin
= get_begin_section_plugin_descriptors();
1483 * Use this first symbol to know whether or not this
1484 * shared object _looks like_ a Babeltrace plugin. Since
1485 * g_module_symbol() failed, assume that this is not a
1486 * Babeltrace plugin, so it's not an error.
1488 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1489 "symbol=\"%s\"", path
,
1490 "__bt_get_begin_section_plugin_descriptors");
1491 status
= BT_FUNC_STATUS_NOT_FOUND
;
1496 * If g_module_symbol() fails for any of the other symbols, fail
1497 * if `fail_on_load_error` is true.
1499 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_plugin_descriptors",
1500 (gpointer
*) &get_end_section_plugin_descriptors
)) {
1501 descriptors_end
= get_end_section_plugin_descriptors();
1503 if (fail_on_load_error
) {
1504 BT_LIB_LOGW_APPEND_CAUSE(
1505 "Cannot resolve plugin symbol: path=\"%s\", "
1506 "symbol=\"%s\"", path
,
1507 "__bt_get_end_section_plugin_descriptors");
1508 status
= BT_FUNC_STATUS_ERROR
;
1511 "Cannot resolve plugin symbol: path=\"%s\", "
1512 "symbol=\"%s\"", path
,
1513 "__bt_get_end_section_plugin_descriptors");
1514 status
= BT_FUNC_STATUS_NOT_FOUND
;
1520 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_plugin_descriptor_attributes",
1521 (gpointer
*) &get_begin_section_plugin_descriptor_attributes
)) {
1522 attrs_begin
= get_begin_section_plugin_descriptor_attributes();
1524 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1525 "symbol=\"%s\"", path
,
1526 "__bt_get_begin_section_plugin_descriptor_attributes");
1529 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_plugin_descriptor_attributes",
1530 (gpointer
*) &get_end_section_plugin_descriptor_attributes
)) {
1531 attrs_end
= get_end_section_plugin_descriptor_attributes();
1533 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1534 "symbol=\"%s\"", path
,
1535 "__bt_get_end_section_plugin_descriptor_attributes");
1538 if ((!!attrs_begin
- !!attrs_end
) != 0) {
1539 if (fail_on_load_error
) {
1540 BT_LIB_LOGW_APPEND_CAUSE(
1541 "Found section start or end symbol, but not both: "
1542 "path=\"%s\", symbol-start=\"%s\", "
1543 "symbol-end=\"%s\", symbol-start-addr=%p, "
1544 "symbol-end-addr=%p",
1545 path
, "__bt_get_begin_section_plugin_descriptor_attributes",
1546 "__bt_get_end_section_plugin_descriptor_attributes",
1547 attrs_begin
, attrs_end
);
1548 status
= BT_FUNC_STATUS_ERROR
;
1551 "Found section start or end symbol, but not both: "
1552 "path=\"%s\", symbol-start=\"%s\", "
1553 "symbol-end=\"%s\", symbol-start-addr=%p, "
1554 "symbol-end-addr=%p",
1555 path
, "__bt_get_begin_section_plugin_descriptor_attributes",
1556 "__bt_get_end_section_plugin_descriptor_attributes",
1557 attrs_begin
, attrs_end
);
1558 status
= BT_FUNC_STATUS_NOT_FOUND
;
1564 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_component_class_descriptors",
1565 (gpointer
*) &get_begin_section_component_class_descriptors
)) {
1566 cc_descriptors_begin
= get_begin_section_component_class_descriptors();
1568 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1569 "symbol=\"%s\"", path
,
1570 "__bt_get_begin_section_component_class_descriptors");
1573 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_component_class_descriptors",
1574 (gpointer
*) &get_end_section_component_class_descriptors
)) {
1575 cc_descriptors_end
= get_end_section_component_class_descriptors();
1577 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1578 "symbol=\"%s\"", path
,
1579 "__bt_get_end_section_component_class_descriptors");
1582 if ((!!cc_descriptors_begin
- !!cc_descriptors_end
) != 0) {
1583 if (fail_on_load_error
) {
1584 BT_LIB_LOGW_APPEND_CAUSE(
1585 "Found section start or end symbol, but not both: "
1586 "path=\"%s\", symbol-start=\"%s\", "
1587 "symbol-end=\"%s\", symbol-start-addr=%p, "
1588 "symbol-end-addr=%p",
1589 path
, "__bt_get_begin_section_component_class_descriptors",
1590 "__bt_get_end_section_component_class_descriptors",
1591 cc_descriptors_begin
, cc_descriptors_end
);
1592 status
= BT_FUNC_STATUS_ERROR
;
1595 "Found section start or end symbol, but not both: "
1596 "path=\"%s\", symbol-start=\"%s\", "
1597 "symbol-end=\"%s\", symbol-start-addr=%p, "
1598 "symbol-end-addr=%p",
1599 path
, "__bt_get_begin_section_component_class_descriptors",
1600 "__bt_get_end_section_component_class_descriptors",
1601 cc_descriptors_begin
, cc_descriptors_end
);
1602 status
= BT_FUNC_STATUS_NOT_FOUND
;
1608 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_component_class_descriptor_attributes",
1609 (gpointer
*) &get_begin_section_component_class_descriptor_attributes
)) {
1610 cc_descr_attrs_begin
= get_begin_section_component_class_descriptor_attributes();
1612 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1613 "symbol=\"%s\"", path
,
1614 "__bt_get_begin_section_component_class_descriptor_attributes");
1617 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_component_class_descriptor_attributes",
1618 (gpointer
*) &get_end_section_component_class_descriptor_attributes
)) {
1619 cc_descr_attrs_end
= get_end_section_component_class_descriptor_attributes();
1621 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1622 "symbol=\"%s\"", path
,
1623 "__bt_get_end_section_component_class_descriptor_attributes");
1626 if ((!!cc_descr_attrs_begin
- !!cc_descr_attrs_end
) != 0) {
1627 if (fail_on_load_error
) {
1628 BT_LIB_LOGW_APPEND_CAUSE(
1629 "Found section start or end symbol, but not both: "
1630 "path=\"%s\", symbol-start=\"%s\", "
1631 "symbol-end=\"%s\", symbol-start-addr=%p, "
1632 "symbol-end-addr=%p",
1633 path
, "__bt_get_begin_section_component_class_descriptor_attributes",
1634 "__bt_get_end_section_component_class_descriptor_attributes",
1635 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1636 status
= BT_FUNC_STATUS_ERROR
;
1639 "Found section start or end symbol, but not both: "
1640 "path=\"%s\", symbol-start=\"%s\", "
1641 "symbol-end=\"%s\", symbol-start-addr=%p, "
1642 "symbol-end-addr=%p",
1643 path
, "__bt_get_begin_section_component_class_descriptor_attributes",
1644 "__bt_get_end_section_component_class_descriptor_attributes",
1645 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1646 status
= BT_FUNC_STATUS_NOT_FOUND
;
1652 /* Initialize plugin */
1653 BT_LOGD_STR("Initializing plugin object.");
1654 status
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
1656 descriptors_begin
, descriptors_end
, attrs_begin
, attrs_end
,
1657 cc_descriptors_begin
, cc_descriptors_end
,
1658 cc_descr_attrs_begin
, cc_descr_attrs_end
, plugin_set_out
);
1661 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle
);
1666 void plugin_comp_class_destroy_listener(struct bt_component_class
*comp_class
,
1669 bt_list_del(&comp_class
->node
);
1670 BT_OBJECT_PUT_REF_AND_RESET(comp_class
->so_handle
);
1671 BT_LOGD("Component class destroyed: removed entry from list: "
1672 "comp-cls-addr=%p", comp_class
);
1675 void bt_plugin_so_on_add_component_class(struct bt_plugin
*plugin
,
1676 struct bt_component_class
*comp_class
)
1678 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
1680 BT_ASSERT(plugin
->spec_data
);
1681 BT_ASSERT(plugin
->type
== BT_PLUGIN_TYPE_SO
);
1683 bt_list_add(&comp_class
->node
, &component_class_list
);
1684 comp_class
->so_handle
= spec
->shared_lib_handle
;
1685 bt_object_get_ref_no_null_check(comp_class
->so_handle
);
1687 /* Add our custom destroy listener */
1688 bt_component_class_add_destroy_listener(comp_class
,
1689 plugin_comp_class_destroy_listener
, NULL
);