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_message_iterator_class_initialize_method msg_iter_initialize
;
298 bt_message_iterator_class_finalize_method msg_iter_finalize
;
299 bt_message_iterator_class_seek_ns_from_origin_method msg_iter_seek_ns_from_origin
;
300 bt_message_iterator_class_seek_beginning_method msg_iter_seek_beginning
;
301 bt_message_iterator_class_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin
;
302 bt_message_iterator_class_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_message_iterator_class_initialize_method msg_iter_initialize
;
313 bt_message_iterator_class_finalize_method msg_iter_finalize
;
314 bt_message_iterator_class_seek_ns_from_origin_method msg_iter_seek_ns_from_origin
;
315 bt_message_iterator_class_seek_beginning_method msg_iter_seek_beginning
;
316 bt_message_iterator_class_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin
;
317 bt_message_iterator_class_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
;
339 struct bt_message_iterator_class
*msg_iter_class
= NULL
;
341 BT_LOGI("Initializing plugin object from descriptors found in sections: "
342 "plugin-addr=%p, plugin-path=\"%s\", "
343 "attrs-begin-addr=%p, attrs-end-addr=%p, "
344 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
345 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p",
347 spec
->shared_lib_handle
->path
?
348 spec
->shared_lib_handle
->path
->str
: NULL
,
349 attrs_begin
, attrs_end
,
350 cc_descriptors_begin
, cc_descriptors_end
,
351 cc_descr_attrs_begin
, cc_descr_attrs_end
);
352 comp_class_full_descriptors
= g_array_new(FALSE
, TRUE
,
353 sizeof(struct comp_class_full_descriptor
));
354 if (!comp_class_full_descriptors
) {
355 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
356 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
360 /* Set mandatory attributes */
361 spec
->descriptor
= descriptor
;
362 bt_plugin_set_name(plugin
, descriptor
->name
);
365 * Find and set optional attributes attached to this plugin
368 for (cur_attr_ptr
= attrs_begin
; cur_attr_ptr
!= attrs_end
; cur_attr_ptr
++) {
369 const struct __bt_plugin_descriptor_attribute
*cur_attr
=
376 if (cur_attr
->plugin_descriptor
!= descriptor
) {
380 switch (cur_attr
->type
) {
381 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT
:
382 spec
->init
= cur_attr
->value
.init
;
384 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT
:
385 spec
->shared_lib_handle
->exit
= cur_attr
->value
.exit
;
387 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR
:
388 bt_plugin_set_author(plugin
, cur_attr
->value
.author
);
390 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE
:
391 bt_plugin_set_license(plugin
, cur_attr
->value
.license
);
393 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
394 bt_plugin_set_description(plugin
, cur_attr
->value
.description
);
396 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION
:
397 bt_plugin_set_version(plugin
,
398 (unsigned int) cur_attr
->value
.version
.major
,
399 (unsigned int) cur_attr
->value
.version
.minor
,
400 (unsigned int) cur_attr
->value
.version
.patch
,
401 cur_attr
->value
.version
.extra
);
404 if (fail_on_load_error
) {
405 BT_LIB_LOGW_APPEND_CAUSE(
406 "Unknown plugin descriptor attribute: "
407 "plugin-path=\"%s\", plugin-name=\"%s\", "
408 "attr-type-name=\"%s\", attr-type-id=%d",
409 spec
->shared_lib_handle
->path
?
410 spec
->shared_lib_handle
->path
->str
:
412 descriptor
->name
, cur_attr
->type_name
,
414 status
= BT_FUNC_STATUS_ERROR
;
418 "Ignoring unknown plugin descriptor attribute: "
419 "plugin-path=\"%s\", plugin-name=\"%s\", "
420 "attr-type-name=\"%s\", attr-type-id=%d",
421 spec
->shared_lib_handle
->path
?
422 spec
->shared_lib_handle
->path
->str
:
424 descriptor
->name
, cur_attr
->type_name
,
433 * Find component class descriptors attached to this plugin
434 * descriptor and initialize corresponding full component class
435 * descriptors in the array.
437 for (cur_cc_descr_ptr
= cc_descriptors_begin
; cur_cc_descr_ptr
!= cc_descriptors_end
; cur_cc_descr_ptr
++) {
438 const struct __bt_plugin_component_class_descriptor
*cur_cc_descr
=
440 struct comp_class_full_descriptor full_descriptor
= {0};
446 if (cur_cc_descr
->plugin_descriptor
!= descriptor
) {
450 full_descriptor
.descriptor
= cur_cc_descr
;
451 g_array_append_val(comp_class_full_descriptors
,
456 * Find component class descriptor attributes attached to this
457 * plugin descriptor and update corresponding full component
458 * class descriptors in the array.
460 for (cur_cc_descr_attr_ptr
= cc_descr_attrs_begin
; cur_cc_descr_attr_ptr
!= cc_descr_attrs_end
; cur_cc_descr_attr_ptr
++) {
461 const struct __bt_plugin_component_class_descriptor_attribute
*cur_cc_descr_attr
=
462 *cur_cc_descr_attr_ptr
;
463 enum bt_component_class_type cc_type
;
465 if (!cur_cc_descr_attr
) {
469 if (cur_cc_descr_attr
->comp_class_descriptor
->plugin_descriptor
!=
474 cc_type
= cur_cc_descr_attr
->comp_class_descriptor
->type
;
476 /* Find the corresponding component class descriptor entry */
477 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
478 struct comp_class_full_descriptor
*cc_full_descr
=
479 &g_array_index(comp_class_full_descriptors
,
480 struct comp_class_full_descriptor
, i
);
482 if (cur_cc_descr_attr
->comp_class_descriptor
!=
483 cc_full_descr
->descriptor
) {
487 switch (cur_cc_descr_attr
->type
) {
488 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
489 cc_full_descr
->description
=
490 cur_cc_descr_attr
->value
.description
;
492 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP
:
493 cc_full_descr
->help
=
494 cur_cc_descr_attr
->value
.help
;
496 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GET_SUPPORTED_MIP_VERSIONS_METHOD
:
498 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
499 cc_full_descr
->methods
.source
.get_supported_mip_versions
=
500 cur_cc_descr_attr
->value
.source_get_supported_mip_versions_method
;
502 case BT_COMPONENT_CLASS_TYPE_FILTER
:
503 cc_full_descr
->methods
.filter
.get_supported_mip_versions
=
504 cur_cc_descr_attr
->value
.filter_get_supported_mip_versions_method
;
506 case BT_COMPONENT_CLASS_TYPE_SINK
:
507 cc_full_descr
->methods
.sink
.get_supported_mip_versions
=
508 cur_cc_descr_attr
->value
.sink_get_supported_mip_versions_method
;
514 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INITIALIZE_METHOD
:
516 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
517 cc_full_descr
->methods
.source
.init
=
518 cur_cc_descr_attr
->value
.source_initialize_method
;
520 case BT_COMPONENT_CLASS_TYPE_FILTER
:
521 cc_full_descr
->methods
.filter
.init
=
522 cur_cc_descr_attr
->value
.filter_initialize_method
;
524 case BT_COMPONENT_CLASS_TYPE_SINK
:
525 cc_full_descr
->methods
.sink
.init
=
526 cur_cc_descr_attr
->value
.sink_initialize_method
;
532 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD
:
534 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
535 cc_full_descr
->methods
.source
.finalize
=
536 cur_cc_descr_attr
->value
.source_finalize_method
;
538 case BT_COMPONENT_CLASS_TYPE_FILTER
:
539 cc_full_descr
->methods
.filter
.finalize
=
540 cur_cc_descr_attr
->value
.filter_finalize_method
;
542 case BT_COMPONENT_CLASS_TYPE_SINK
:
543 cc_full_descr
->methods
.sink
.finalize
=
544 cur_cc_descr_attr
->value
.sink_finalize_method
;
550 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD
:
552 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
553 cc_full_descr
->methods
.source
.query
=
554 cur_cc_descr_attr
->value
.source_query_method
;
556 case BT_COMPONENT_CLASS_TYPE_FILTER
:
557 cc_full_descr
->methods
.filter
.query
=
558 cur_cc_descr_attr
->value
.filter_query_method
;
560 case BT_COMPONENT_CLASS_TYPE_SINK
:
561 cc_full_descr
->methods
.sink
.query
=
562 cur_cc_descr_attr
->value
.sink_query_method
;
568 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INPUT_PORT_CONNECTED_METHOD
:
570 case BT_COMPONENT_CLASS_TYPE_FILTER
:
571 cc_full_descr
->methods
.filter
.input_port_connected
=
572 cur_cc_descr_attr
->value
.filter_input_port_connected_method
;
574 case BT_COMPONENT_CLASS_TYPE_SINK
:
575 cc_full_descr
->methods
.sink
.input_port_connected
=
576 cur_cc_descr_attr
->value
.sink_input_port_connected_method
;
582 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_OUTPUT_PORT_CONNECTED_METHOD
:
584 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
585 cc_full_descr
->methods
.source
.output_port_connected
=
586 cur_cc_descr_attr
->value
.source_output_port_connected_method
;
588 case BT_COMPONENT_CLASS_TYPE_FILTER
:
589 cc_full_descr
->methods
.filter
.output_port_connected
=
590 cur_cc_descr_attr
->value
.filter_output_port_connected_method
;
596 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GRAPH_IS_CONFIGURED_METHOD
:
598 case BT_COMPONENT_CLASS_TYPE_SINK
:
599 cc_full_descr
->methods
.sink
.graph_is_configured
=
600 cur_cc_descr_attr
->value
.sink_graph_is_configured_method
;
606 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_INITIALIZE_METHOD
:
608 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
609 cc_full_descr
->methods
.source
.msg_iter_initialize
=
610 cur_cc_descr_attr
->value
.msg_iter_initialize_method
;
612 case BT_COMPONENT_CLASS_TYPE_FILTER
:
613 cc_full_descr
->methods
.filter
.msg_iter_initialize
=
614 cur_cc_descr_attr
->value
.msg_iter_initialize_method
;
620 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_FINALIZE_METHOD
:
622 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
623 cc_full_descr
->methods
.source
.msg_iter_finalize
=
624 cur_cc_descr_attr
->value
.msg_iter_finalize_method
;
626 case BT_COMPONENT_CLASS_TYPE_FILTER
:
627 cc_full_descr
->methods
.filter
.msg_iter_finalize
=
628 cur_cc_descr_attr
->value
.msg_iter_finalize_method
;
634 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_NS_FROM_ORIGIN_METHOD
:
636 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
637 cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
=
638 cur_cc_descr_attr
->value
.msg_iter_seek_ns_from_origin_method
;
640 case BT_COMPONENT_CLASS_TYPE_FILTER
:
641 cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
=
642 cur_cc_descr_attr
->value
.msg_iter_seek_ns_from_origin_method
;
648 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_BEGINNING_METHOD
:
650 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
651 cc_full_descr
->methods
.source
.msg_iter_seek_beginning
=
652 cur_cc_descr_attr
->value
.msg_iter_seek_beginning_method
;
654 case BT_COMPONENT_CLASS_TYPE_FILTER
:
655 cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
=
656 cur_cc_descr_attr
->value
.msg_iter_seek_beginning_method
;
662 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_NS_FROM_ORIGIN_METHOD
:
664 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
665 cc_full_descr
->methods
.source
.msg_iter_can_seek_ns_from_origin
=
666 cur_cc_descr_attr
->value
.msg_iter_can_seek_ns_from_origin_method
;
668 case BT_COMPONENT_CLASS_TYPE_FILTER
:
669 cc_full_descr
->methods
.filter
.msg_iter_can_seek_ns_from_origin
=
670 cur_cc_descr_attr
->value
.msg_iter_can_seek_ns_from_origin_method
;
676 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_BEGINNING_METHOD
:
678 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
679 cc_full_descr
->methods
.source
.msg_iter_can_seek_beginning
=
680 cur_cc_descr_attr
->value
.msg_iter_can_seek_beginning_method
;
682 case BT_COMPONENT_CLASS_TYPE_FILTER
:
683 cc_full_descr
->methods
.filter
.msg_iter_can_seek_beginning
=
684 cur_cc_descr_attr
->value
.msg_iter_can_seek_beginning_method
;
691 if (fail_on_load_error
) {
692 BT_LIB_LOGW_APPEND_CAUSE(
693 "Unknown component class descriptor attribute: "
694 "plugin-path=\"%s\", "
695 "plugin-name=\"%s\", "
696 "comp-class-name=\"%s\", "
697 "comp-class-type=%s, "
698 "attr-type-name=\"%s\", "
700 spec
->shared_lib_handle
->path
?
701 spec
->shared_lib_handle
->path
->str
:
704 cur_cc_descr_attr
->comp_class_descriptor
->name
,
705 bt_component_class_type_string(
706 cur_cc_descr_attr
->comp_class_descriptor
->type
),
707 cur_cc_descr_attr
->type_name
,
708 cur_cc_descr_attr
->type
);
709 status
= BT_FUNC_STATUS_ERROR
;
713 "Ignoring unknown component class descriptor attribute: "
714 "plugin-path=\"%s\", "
715 "plugin-name=\"%s\", "
716 "comp-class-name=\"%s\", "
717 "comp-class-type=%s, "
718 "attr-type-name=\"%s\", "
720 spec
->shared_lib_handle
->path
?
721 spec
->shared_lib_handle
->path
->str
:
724 cur_cc_descr_attr
->comp_class_descriptor
->name
,
725 bt_component_class_type_string(
726 cur_cc_descr_attr
->comp_class_descriptor
->type
),
727 cur_cc_descr_attr
->type_name
,
728 cur_cc_descr_attr
->type
);
736 /* Initialize plugin */
738 enum bt_plugin_initialize_func_status init_status
;
740 BT_LOGD_STR("Calling user's plugin initialization function.");
741 init_status
= spec
->init((void *) plugin
);
742 BT_LOGD("User function returned: status=%s",
743 bt_common_func_status_string(init_status
));
745 if (init_status
< 0) {
746 if (fail_on_load_error
) {
747 BT_LIB_LOGW_APPEND_CAUSE(
748 "User's plugin initialization function failed: "
750 bt_common_func_status_string(init_status
));
751 status
= init_status
;
755 "User's plugin initialization function failed: "
757 bt_common_func_status_string(init_status
));
758 status
= BT_FUNC_STATUS_NOT_FOUND
;
765 spec
->shared_lib_handle
->init_called
= BT_TRUE
;
767 /* Add described component classes to plugin */
768 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
769 struct comp_class_full_descriptor
*cc_full_descr
=
770 &g_array_index(comp_class_full_descriptors
,
771 struct comp_class_full_descriptor
, i
);
772 struct bt_component_class
*comp_class
= NULL
;
773 struct bt_component_class_source
*src_comp_class
= NULL
;
774 struct bt_component_class_filter
*flt_comp_class
= NULL
;
775 struct bt_component_class_sink
*sink_comp_class
= NULL
;
777 BT_LOGI("Creating and setting properties of plugin's component class: "
778 "plugin-path=\"%s\", plugin-name=\"%s\", "
779 "comp-class-name=\"%s\", comp-class-type=%s",
780 spec
->shared_lib_handle
->path
?
781 spec
->shared_lib_handle
->path
->str
:
784 cc_full_descr
->descriptor
->name
,
785 bt_component_class_type_string(
786 cc_full_descr
->descriptor
->type
));
788 if (cc_full_descr
->descriptor
->type
== BT_COMPONENT_CLASS_TYPE_SOURCE
||
789 cc_full_descr
->descriptor
->type
== BT_COMPONENT_CLASS_TYPE_FILTER
) {
790 bt_message_iterator_class_next_method next_method
;
791 bt_message_iterator_class_initialize_method init_method
;
792 bt_message_iterator_class_finalize_method fini_method
;
793 bt_message_iterator_class_seek_ns_from_origin_method seek_ns_from_origin_method
;
794 bt_message_iterator_class_seek_beginning_method seek_beginning_method
;
795 bt_message_iterator_class_can_seek_ns_from_origin_method can_seek_ns_from_origin_method
;
796 bt_message_iterator_class_can_seek_beginning_method can_seek_beginning_method
;
798 if (cc_full_descr
->descriptor
->type
== BT_COMPONENT_CLASS_TYPE_SOURCE
) {
799 next_method
= cc_full_descr
->descriptor
->methods
.source
.msg_iter_next
;
800 init_method
= cc_full_descr
->methods
.source
.msg_iter_initialize
;
801 fini_method
= cc_full_descr
->methods
.source
.msg_iter_finalize
;
802 seek_ns_from_origin_method
= cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
;
803 can_seek_ns_from_origin_method
= cc_full_descr
->methods
.source
.msg_iter_can_seek_ns_from_origin
;
804 seek_beginning_method
= cc_full_descr
->methods
.source
.msg_iter_seek_beginning
;
805 can_seek_beginning_method
= cc_full_descr
->methods
.source
.msg_iter_can_seek_beginning
;
807 next_method
= cc_full_descr
->descriptor
->methods
.filter
.msg_iter_next
;
808 init_method
= cc_full_descr
->methods
.filter
.msg_iter_initialize
;
809 fini_method
= cc_full_descr
->methods
.filter
.msg_iter_finalize
;
810 seek_ns_from_origin_method
= cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
;
811 can_seek_ns_from_origin_method
= cc_full_descr
->methods
.filter
.msg_iter_can_seek_ns_from_origin
;
812 seek_beginning_method
= cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
;
813 can_seek_beginning_method
= cc_full_descr
->methods
.filter
.msg_iter_can_seek_beginning
;
816 msg_iter_class
= bt_message_iterator_class_create(next_method
);
817 if (!msg_iter_class
) {
818 BT_LIB_LOGE_APPEND_CAUSE(
819 "Cannot create message iterator class.");
820 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
825 ret
= bt_message_iterator_class_set_initialize_method(
826 msg_iter_class
, init_method
);
828 BT_LIB_LOGE_APPEND_CAUSE(
829 "Cannot set message iterator initialization method.");
830 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
836 ret
= bt_message_iterator_class_set_finalize_method(
837 msg_iter_class
, fini_method
);
839 BT_LIB_LOGE_APPEND_CAUSE(
840 "Cannot set message iterator finalization method.");
841 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
846 if (seek_ns_from_origin_method
) {
847 ret
= bt_message_iterator_class_set_seek_ns_from_origin_methods(
849 seek_ns_from_origin_method
,
850 can_seek_ns_from_origin_method
);
852 BT_LIB_LOGE_APPEND_CAUSE(
853 "Cannot set message iterator \"seek nanoseconds from origin\" methods.");
854 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
859 if (seek_beginning_method
) {
860 ret
= bt_message_iterator_class_set_seek_beginning_methods(
862 seek_beginning_method
,
863 can_seek_beginning_method
);
865 BT_LIB_LOGE_APPEND_CAUSE(
866 "Cannot set message iterator \"seek beginning\" methods.");
867 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
873 switch (cc_full_descr
->descriptor
->type
) {
874 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
875 BT_ASSERT(msg_iter_class
);
877 src_comp_class
= bt_component_class_source_create(
878 cc_full_descr
->descriptor
->name
, msg_iter_class
);
879 comp_class
= bt_component_class_source_as_component_class(
882 case BT_COMPONENT_CLASS_TYPE_FILTER
:
883 BT_ASSERT(msg_iter_class
);
885 flt_comp_class
= bt_component_class_filter_create(
886 cc_full_descr
->descriptor
->name
, msg_iter_class
);
887 comp_class
= bt_component_class_filter_as_component_class(
890 case BT_COMPONENT_CLASS_TYPE_SINK
:
891 BT_ASSERT(!msg_iter_class
);
893 sink_comp_class
= bt_component_class_sink_create(
894 cc_full_descr
->descriptor
->name
,
895 cc_full_descr
->descriptor
->methods
.sink
.consume
);
896 comp_class
= bt_component_class_sink_as_component_class(
900 if (fail_on_load_error
) {
901 BT_LIB_LOGW_APPEND_CAUSE(
902 "Unknown component class type: "
903 "plugin-path=\"%s\", plugin-name=\"%s\", "
904 "comp-class-name=\"%s\", comp-class-type=%d",
905 spec
->shared_lib_handle
->path
->str
?
906 spec
->shared_lib_handle
->path
->str
:
909 cc_full_descr
->descriptor
->name
,
910 cc_full_descr
->descriptor
->type
);
911 status
= BT_FUNC_STATUS_ERROR
;
915 "Ignoring unknown component class type: "
916 "plugin-path=\"%s\", plugin-name=\"%s\", "
917 "comp-class-name=\"%s\", comp-class-type=%d",
918 spec
->shared_lib_handle
->path
->str
?
919 spec
->shared_lib_handle
->path
->str
:
922 cc_full_descr
->descriptor
->name
,
923 cc_full_descr
->descriptor
->type
);
929 BT_LIB_LOGE_APPEND_CAUSE(
930 "Cannot create component class.");
931 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
936 * The component class has taken a reference on the message
937 * iterator class, so we can drop ours. The message iterator
938 * class will get destroyed at the same time as the component
941 bt_message_iterator_class_put_ref(msg_iter_class
);
942 msg_iter_class
= NULL
;
944 if (cc_full_descr
->description
) {
945 ret
= bt_component_class_set_description(
946 comp_class
, cc_full_descr
->description
);
948 BT_LIB_LOGE_APPEND_CAUSE(
949 "Cannot set component class's description.");
950 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
951 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
956 if (cc_full_descr
->help
) {
957 ret
= bt_component_class_set_help(comp_class
,
958 cc_full_descr
->help
);
960 BT_LIB_LOGE_APPEND_CAUSE(
961 "Cannot set component class's help string.");
962 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
963 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
968 switch (cc_full_descr
->descriptor
->type
) {
969 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
970 if (cc_full_descr
->methods
.source
.get_supported_mip_versions
) {
971 ret
= bt_component_class_source_set_get_supported_mip_versions_method(
973 cc_full_descr
->methods
.source
.get_supported_mip_versions
);
975 BT_LIB_LOGE_APPEND_CAUSE(
976 "Cannot set source component class's \"get supported MIP versions\" method.");
977 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
978 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
983 if (cc_full_descr
->methods
.source
.init
) {
984 ret
= bt_component_class_source_set_initialize_method(
986 cc_full_descr
->methods
.source
.init
);
988 BT_LIB_LOGE_APPEND_CAUSE(
989 "Cannot set source component class's initialization method.");
990 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
991 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
996 if (cc_full_descr
->methods
.source
.finalize
) {
997 ret
= bt_component_class_source_set_finalize_method(
999 cc_full_descr
->methods
.source
.finalize
);
1001 BT_LIB_LOGE_APPEND_CAUSE(
1002 "Cannot set source component class's finalization method.");
1003 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1004 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
1009 if (cc_full_descr
->methods
.source
.query
) {
1010 ret
= bt_component_class_source_set_query_method(
1012 cc_full_descr
->methods
.source
.query
);
1014 BT_LIB_LOGE_APPEND_CAUSE(
1015 "Cannot set source component class's query method.");
1016 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1017 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
1022 if (cc_full_descr
->methods
.source
.output_port_connected
) {
1023 ret
= bt_component_class_source_set_output_port_connected_method(
1025 cc_full_descr
->methods
.source
.output_port_connected
);
1027 BT_LIB_LOGE_APPEND_CAUSE(
1028 "Cannot set source component class's \"output port connected\" method.");
1029 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1030 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
1036 case BT_COMPONENT_CLASS_TYPE_FILTER
:
1037 if (cc_full_descr
->methods
.filter
.get_supported_mip_versions
) {
1038 ret
= bt_component_class_filter_set_get_supported_mip_versions_method(
1040 cc_full_descr
->methods
.filter
.get_supported_mip_versions
);
1042 BT_LIB_LOGE_APPEND_CAUSE(
1043 "Cannot set filter component class's \"get supported MIP versions\" method.");
1044 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1045 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1050 if (cc_full_descr
->methods
.filter
.init
) {
1051 ret
= bt_component_class_filter_set_initialize_method(
1053 cc_full_descr
->methods
.filter
.init
);
1055 BT_LIB_LOGE_APPEND_CAUSE(
1056 "Cannot set filter component class's initialization method.");
1057 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1058 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1063 if (cc_full_descr
->methods
.filter
.finalize
) {
1064 ret
= bt_component_class_filter_set_finalize_method(
1066 cc_full_descr
->methods
.filter
.finalize
);
1068 BT_LIB_LOGE_APPEND_CAUSE(
1069 "Cannot set filter component class's finalization method.");
1070 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1071 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1076 if (cc_full_descr
->methods
.filter
.query
) {
1077 ret
= bt_component_class_filter_set_query_method(
1079 cc_full_descr
->methods
.filter
.query
);
1081 BT_LIB_LOGE_APPEND_CAUSE(
1082 "Cannot set filter component class's query method.");
1083 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1084 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1089 if (cc_full_descr
->methods
.filter
.input_port_connected
) {
1090 ret
= bt_component_class_filter_set_input_port_connected_method(
1092 cc_full_descr
->methods
.filter
.input_port_connected
);
1094 BT_LIB_LOGE_APPEND_CAUSE(
1095 "Cannot set filter component class's \"input port connected\" method.");
1096 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1097 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1102 if (cc_full_descr
->methods
.filter
.output_port_connected
) {
1103 ret
= bt_component_class_filter_set_output_port_connected_method(
1105 cc_full_descr
->methods
.filter
.output_port_connected
);
1107 BT_LIB_LOGE_APPEND_CAUSE(
1108 "Cannot set filter component class's \"output port connected\" method.");
1109 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1110 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1116 case BT_COMPONENT_CLASS_TYPE_SINK
:
1117 if (cc_full_descr
->methods
.sink
.get_supported_mip_versions
) {
1118 ret
= bt_component_class_sink_set_get_supported_mip_versions_method(
1120 cc_full_descr
->methods
.sink
.get_supported_mip_versions
);
1122 BT_LIB_LOGE_APPEND_CAUSE(
1123 "Cannot set sink component class's \"get supported MIP versions\" method.");
1124 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1125 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1130 if (cc_full_descr
->methods
.sink
.init
) {
1131 ret
= bt_component_class_sink_set_initialize_method(
1133 cc_full_descr
->methods
.sink
.init
);
1135 BT_LIB_LOGE_APPEND_CAUSE(
1136 "Cannot set sink component class's initialization method.");
1137 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1138 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1143 if (cc_full_descr
->methods
.sink
.finalize
) {
1144 ret
= bt_component_class_sink_set_finalize_method(
1146 cc_full_descr
->methods
.sink
.finalize
);
1148 BT_LIB_LOGE_APPEND_CAUSE(
1149 "Cannot set sink component class's finalization method.");
1150 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1151 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1156 if (cc_full_descr
->methods
.sink
.query
) {
1157 ret
= bt_component_class_sink_set_query_method(
1159 cc_full_descr
->methods
.sink
.query
);
1161 BT_LIB_LOGE_APPEND_CAUSE(
1162 "Cannot set sink component class's query method.");
1163 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1164 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1169 if (cc_full_descr
->methods
.sink
.input_port_connected
) {
1170 ret
= bt_component_class_sink_set_input_port_connected_method(
1172 cc_full_descr
->methods
.sink
.input_port_connected
);
1174 BT_LIB_LOGE_APPEND_CAUSE(
1175 "Cannot set sink component class's \"input port connected\" method.");
1176 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1177 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1182 if (cc_full_descr
->methods
.sink
.graph_is_configured
) {
1183 ret
= bt_component_class_sink_set_graph_is_configured_method(
1185 cc_full_descr
->methods
.sink
.graph_is_configured
);
1187 BT_LIB_LOGE_APPEND_CAUSE(
1188 "Cannot set sink component class's \"graph is configured\" method.");
1189 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1190 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1201 * Add component class to the plugin object.
1203 * This will call back
1204 * bt_plugin_so_on_add_component_class() so that we can
1205 * add a mapping in the component class list when we
1206 * know the component class is successfully added.
1208 status
= bt_plugin_add_component_class(plugin
,
1209 (void *) comp_class
);
1210 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
1212 BT_LIB_LOGE_APPEND_CAUSE(
1213 "Cannot add component class to plugin.");
1219 bt_message_iterator_class_put_ref(msg_iter_class
);
1220 g_array_free(comp_class_full_descriptors
, TRUE
);
1225 struct bt_plugin
*bt_plugin_so_create_empty(
1226 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
)
1228 struct bt_plugin
*plugin
;
1229 struct bt_plugin_so_spec_data
*spec
;
1231 plugin
= bt_plugin_create_empty(BT_PLUGIN_TYPE_SO
);
1236 plugin
->destroy_spec_data
= bt_plugin_so_destroy_spec_data
;
1237 plugin
->spec_data
= g_new0(struct bt_plugin_so_spec_data
, 1);
1238 if (!plugin
->spec_data
) {
1239 BT_LIB_LOGE_APPEND_CAUSE(
1240 "Failed to allocate one SO plugin specific data structure.");
1244 spec
= plugin
->spec_data
;
1245 spec
->shared_lib_handle
= shared_lib_handle
;
1246 bt_object_get_ref_no_null_check(spec
->shared_lib_handle
);
1250 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1257 size_t count_non_null_items_in_section(const void *begin
, const void *end
)
1260 const int * const *begin_int
= (const int * const *) begin
;
1261 const int * const *end_int
= (const int * const *) end
;
1262 const int * const *iter
;
1264 for (iter
= begin_int
; iter
!= end_int
; iter
++) {
1274 int bt_plugin_so_create_all_from_sections(
1275 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
,
1276 bool fail_on_load_error
,
1277 struct __bt_plugin_descriptor
const * const *descriptors_begin
,
1278 struct __bt_plugin_descriptor
const * const *descriptors_end
,
1279 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
1280 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
1281 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
1282 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
1283 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
1284 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
,
1285 struct bt_plugin_set
**plugin_set_out
)
1287 int status
= BT_FUNC_STATUS_OK
;
1288 size_t descriptor_count
;
1290 size_t cc_descriptors_count
;
1291 size_t cc_descr_attrs_count
;
1294 BT_ASSERT(shared_lib_handle
);
1295 BT_ASSERT(plugin_set_out
);
1296 *plugin_set_out
= NULL
;
1297 descriptor_count
= count_non_null_items_in_section(descriptors_begin
, descriptors_end
);
1298 attrs_count
= count_non_null_items_in_section(attrs_begin
, attrs_end
);
1299 cc_descriptors_count
= count_non_null_items_in_section(cc_descriptors_begin
, cc_descriptors_end
);
1300 cc_descr_attrs_count
= count_non_null_items_in_section(cc_descr_attrs_begin
, cc_descr_attrs_end
);
1301 BT_LOGI("Creating all SO plugins from sections: "
1302 "plugin-path=\"%s\", "
1303 "descr-begin-addr=%p, descr-end-addr=%p, "
1304 "attrs-begin-addr=%p, attrs-end-addr=%p, "
1305 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
1306 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p, "
1307 "descr-count=%zu, attrs-count=%zu, "
1308 "cc-descr-count=%zu, cc-descr-attrs-count=%zu",
1309 shared_lib_handle
->path
? shared_lib_handle
->path
->str
: NULL
,
1310 descriptors_begin
, descriptors_end
,
1311 attrs_begin
, attrs_end
,
1312 cc_descriptors_begin
, cc_descriptors_end
,
1313 cc_descr_attrs_begin
, cc_descr_attrs_end
,
1314 descriptor_count
, attrs_count
,
1315 cc_descriptors_count
, cc_descr_attrs_count
);
1316 *plugin_set_out
= bt_plugin_set_create();
1317 if (!*plugin_set_out
) {
1318 BT_LIB_LOGE_APPEND_CAUSE("Cannot create empty plugin set.");
1319 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1323 for (i
= 0; i
< descriptors_end
- descriptors_begin
; i
++) {
1324 const struct __bt_plugin_descriptor
*descriptor
=
1325 descriptors_begin
[i
];
1326 struct bt_plugin
*plugin
;
1332 BT_LOGI("Creating plugin object for plugin: name=\"%s\"",
1334 plugin
= bt_plugin_so_create_empty(shared_lib_handle
);
1336 BT_LIB_LOGE_APPEND_CAUSE(
1337 "Cannot create empty shared library handle.");
1338 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1342 if (shared_lib_handle
->path
) {
1343 bt_plugin_set_path(plugin
,
1344 shared_lib_handle
->path
->str
);
1347 status
= bt_plugin_so_init(plugin
, fail_on_load_error
,
1348 descriptor
, attrs_begin
, attrs_end
,
1349 cc_descriptors_begin
, cc_descriptors_end
,
1350 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1351 if (status
== BT_FUNC_STATUS_OK
) {
1352 /* Add to plugin set */
1353 bt_plugin_set_add_plugin(*plugin_set_out
, plugin
);
1354 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1355 } else if (status
< 0) {
1357 * bt_plugin_so_init() handles
1358 * `fail_on_load_error`, so this is a "real"
1361 BT_LIB_LOGW_APPEND_CAUSE(
1362 "Cannot initialize SO plugin object from sections.");
1363 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1370 BT_ASSERT(*plugin_set_out
);
1372 if ((*plugin_set_out
)->plugins
->len
== 0) {
1373 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out
);
1374 status
= BT_FUNC_STATUS_NOT_FOUND
;
1380 BT_ASSERT(status
< 0);
1381 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out
);
1388 int bt_plugin_so_create_all_from_static(bool fail_on_load_error
,
1389 struct bt_plugin_set
**plugin_set_out
)
1392 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
1394 BT_ASSERT(plugin_set_out
);
1395 *plugin_set_out
= NULL
;
1396 status
= bt_plugin_so_shared_lib_handle_create(NULL
,
1397 &shared_lib_handle
);
1398 if (status
!= BT_FUNC_STATUS_OK
) {
1399 BT_ASSERT(!shared_lib_handle
);
1403 BT_ASSERT(shared_lib_handle
);
1404 BT_LOGD_STR("Creating all SO plugins from built-in plugins.");
1405 status
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
1407 __bt_get_begin_section_plugin_descriptors(),
1408 __bt_get_end_section_plugin_descriptors(),
1409 __bt_get_begin_section_plugin_descriptor_attributes(),
1410 __bt_get_end_section_plugin_descriptor_attributes(),
1411 __bt_get_begin_section_component_class_descriptors(),
1412 __bt_get_end_section_component_class_descriptors(),
1413 __bt_get_begin_section_component_class_descriptor_attributes(),
1414 __bt_get_end_section_component_class_descriptor_attributes(),
1416 BT_ASSERT((status
== BT_FUNC_STATUS_OK
&& *plugin_set_out
&&
1417 (*plugin_set_out
)->plugins
->len
> 0) || !*plugin_set_out
);
1420 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle
);
1425 int bt_plugin_so_create_all_from_file(const char *path
,
1426 bool fail_on_load_error
, struct bt_plugin_set
**plugin_set_out
)
1430 struct __bt_plugin_descriptor
const * const *descriptors_begin
= NULL
;
1431 struct __bt_plugin_descriptor
const * const *descriptors_end
= NULL
;
1432 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
= NULL
;
1433 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
= NULL
;
1434 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
= NULL
;
1435 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
= NULL
;
1436 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
= NULL
;
1437 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
= NULL
;
1438 struct __bt_plugin_descriptor
const * const *(*get_begin_section_plugin_descriptors
)(void);
1439 struct __bt_plugin_descriptor
const * const *(*get_end_section_plugin_descriptors
)(void);
1440 struct __bt_plugin_descriptor_attribute
const * const *(*get_begin_section_plugin_descriptor_attributes
)(void);
1441 struct __bt_plugin_descriptor_attribute
const * const *(*get_end_section_plugin_descriptor_attributes
)(void);
1442 struct __bt_plugin_component_class_descriptor
const * const *(*get_begin_section_component_class_descriptors
)(void);
1443 struct __bt_plugin_component_class_descriptor
const * const *(*get_end_section_component_class_descriptors
)(void);
1444 struct __bt_plugin_component_class_descriptor_attribute
const * const *(*get_begin_section_component_class_descriptor_attributes
)(void);
1445 struct __bt_plugin_component_class_descriptor_attribute
const * const *(*get_end_section_component_class_descriptor_attributes
)(void);
1446 bt_bool is_libtool_wrapper
= BT_FALSE
, is_shared_object
= BT_FALSE
;
1447 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
1450 BT_ASSERT(plugin_set_out
);
1451 *plugin_set_out
= NULL
;
1452 path_len
= strlen(path
);
1455 * An SO plugin file must have a known plugin file suffix. So the file
1456 * path must be longer than the suffix length.
1458 if (path_len
<= PLUGIN_SUFFIX_LEN
) {
1459 BT_LOGI("Path is too short to be an `.so` or `.la` plugin file:"
1460 "path=%s, path-length=%zu, min-length=%zu",
1461 path
, path_len
, PLUGIN_SUFFIX_LEN
);
1462 status
= BT_FUNC_STATUS_NOT_FOUND
;
1466 BT_LOGI("Trying to create all SO plugins from file: path=\"%s\"", path
);
1470 * Check if the file ends with a known plugin file type suffix
1471 * (i.e. .so or .la on Linux).
1473 is_libtool_wrapper
= !strncmp(LIBTOOL_PLUGIN_SUFFIX
,
1474 path
+ path_len
- LIBTOOL_PLUGIN_SUFFIX_LEN
,
1475 LIBTOOL_PLUGIN_SUFFIX_LEN
);
1476 is_shared_object
= !strncmp(NATIVE_PLUGIN_SUFFIX
,
1477 path
+ path_len
- NATIVE_PLUGIN_SUFFIX_LEN
,
1478 NATIVE_PLUGIN_SUFFIX_LEN
);
1479 if (!is_shared_object
&& !is_libtool_wrapper
) {
1480 /* Name indicates this is not a plugin file; not an error */
1481 BT_LOGI("File is not an SO plugin file: path=\"%s\"", path
);
1482 status
= BT_FUNC_STATUS_NOT_FOUND
;
1486 status
= bt_plugin_so_shared_lib_handle_create(path
,
1487 &shared_lib_handle
);
1488 if (status
!= BT_FUNC_STATUS_OK
) {
1489 /* bt_plugin_so_shared_lib_handle_create() logs more details */
1490 BT_ASSERT(!shared_lib_handle
);
1494 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_plugin_descriptors",
1495 (gpointer
*) &get_begin_section_plugin_descriptors
)) {
1496 descriptors_begin
= get_begin_section_plugin_descriptors();
1499 * Use this first symbol to know whether or not this
1500 * shared object _looks like_ a Babeltrace plugin. Since
1501 * g_module_symbol() failed, assume that this is not a
1502 * Babeltrace plugin, so it's not an error.
1504 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1505 "symbol=\"%s\"", path
,
1506 "__bt_get_begin_section_plugin_descriptors");
1507 status
= BT_FUNC_STATUS_NOT_FOUND
;
1512 * If g_module_symbol() fails for any of the other symbols, fail
1513 * if `fail_on_load_error` is true.
1515 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_plugin_descriptors",
1516 (gpointer
*) &get_end_section_plugin_descriptors
)) {
1517 descriptors_end
= get_end_section_plugin_descriptors();
1519 if (fail_on_load_error
) {
1520 BT_LIB_LOGW_APPEND_CAUSE(
1521 "Cannot resolve plugin symbol: path=\"%s\", "
1522 "symbol=\"%s\"", path
,
1523 "__bt_get_end_section_plugin_descriptors");
1524 status
= BT_FUNC_STATUS_ERROR
;
1527 "Cannot resolve plugin symbol: path=\"%s\", "
1528 "symbol=\"%s\"", path
,
1529 "__bt_get_end_section_plugin_descriptors");
1530 status
= BT_FUNC_STATUS_NOT_FOUND
;
1536 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_plugin_descriptor_attributes",
1537 (gpointer
*) &get_begin_section_plugin_descriptor_attributes
)) {
1538 attrs_begin
= get_begin_section_plugin_descriptor_attributes();
1540 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1541 "symbol=\"%s\"", path
,
1542 "__bt_get_begin_section_plugin_descriptor_attributes");
1545 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_plugin_descriptor_attributes",
1546 (gpointer
*) &get_end_section_plugin_descriptor_attributes
)) {
1547 attrs_end
= get_end_section_plugin_descriptor_attributes();
1549 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1550 "symbol=\"%s\"", path
,
1551 "__bt_get_end_section_plugin_descriptor_attributes");
1554 if ((!!attrs_begin
- !!attrs_end
) != 0) {
1555 if (fail_on_load_error
) {
1556 BT_LIB_LOGW_APPEND_CAUSE(
1557 "Found section start or end symbol, but not both: "
1558 "path=\"%s\", symbol-start=\"%s\", "
1559 "symbol-end=\"%s\", symbol-start-addr=%p, "
1560 "symbol-end-addr=%p",
1561 path
, "__bt_get_begin_section_plugin_descriptor_attributes",
1562 "__bt_get_end_section_plugin_descriptor_attributes",
1563 attrs_begin
, attrs_end
);
1564 status
= BT_FUNC_STATUS_ERROR
;
1567 "Found section start or end symbol, but not both: "
1568 "path=\"%s\", symbol-start=\"%s\", "
1569 "symbol-end=\"%s\", symbol-start-addr=%p, "
1570 "symbol-end-addr=%p",
1571 path
, "__bt_get_begin_section_plugin_descriptor_attributes",
1572 "__bt_get_end_section_plugin_descriptor_attributes",
1573 attrs_begin
, attrs_end
);
1574 status
= BT_FUNC_STATUS_NOT_FOUND
;
1580 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_component_class_descriptors",
1581 (gpointer
*) &get_begin_section_component_class_descriptors
)) {
1582 cc_descriptors_begin
= get_begin_section_component_class_descriptors();
1584 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1585 "symbol=\"%s\"", path
,
1586 "__bt_get_begin_section_component_class_descriptors");
1589 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_component_class_descriptors",
1590 (gpointer
*) &get_end_section_component_class_descriptors
)) {
1591 cc_descriptors_end
= get_end_section_component_class_descriptors();
1593 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1594 "symbol=\"%s\"", path
,
1595 "__bt_get_end_section_component_class_descriptors");
1598 if ((!!cc_descriptors_begin
- !!cc_descriptors_end
) != 0) {
1599 if (fail_on_load_error
) {
1600 BT_LIB_LOGW_APPEND_CAUSE(
1601 "Found section start or end symbol, but not both: "
1602 "path=\"%s\", symbol-start=\"%s\", "
1603 "symbol-end=\"%s\", symbol-start-addr=%p, "
1604 "symbol-end-addr=%p",
1605 path
, "__bt_get_begin_section_component_class_descriptors",
1606 "__bt_get_end_section_component_class_descriptors",
1607 cc_descriptors_begin
, cc_descriptors_end
);
1608 status
= BT_FUNC_STATUS_ERROR
;
1611 "Found section start or end symbol, but not both: "
1612 "path=\"%s\", symbol-start=\"%s\", "
1613 "symbol-end=\"%s\", symbol-start-addr=%p, "
1614 "symbol-end-addr=%p",
1615 path
, "__bt_get_begin_section_component_class_descriptors",
1616 "__bt_get_end_section_component_class_descriptors",
1617 cc_descriptors_begin
, cc_descriptors_end
);
1618 status
= BT_FUNC_STATUS_NOT_FOUND
;
1624 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_component_class_descriptor_attributes",
1625 (gpointer
*) &get_begin_section_component_class_descriptor_attributes
)) {
1626 cc_descr_attrs_begin
= get_begin_section_component_class_descriptor_attributes();
1628 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1629 "symbol=\"%s\"", path
,
1630 "__bt_get_begin_section_component_class_descriptor_attributes");
1633 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_component_class_descriptor_attributes",
1634 (gpointer
*) &get_end_section_component_class_descriptor_attributes
)) {
1635 cc_descr_attrs_end
= get_end_section_component_class_descriptor_attributes();
1637 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1638 "symbol=\"%s\"", path
,
1639 "__bt_get_end_section_component_class_descriptor_attributes");
1642 if ((!!cc_descr_attrs_begin
- !!cc_descr_attrs_end
) != 0) {
1643 if (fail_on_load_error
) {
1644 BT_LIB_LOGW_APPEND_CAUSE(
1645 "Found section start or end symbol, but not both: "
1646 "path=\"%s\", symbol-start=\"%s\", "
1647 "symbol-end=\"%s\", symbol-start-addr=%p, "
1648 "symbol-end-addr=%p",
1649 path
, "__bt_get_begin_section_component_class_descriptor_attributes",
1650 "__bt_get_end_section_component_class_descriptor_attributes",
1651 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1652 status
= BT_FUNC_STATUS_ERROR
;
1655 "Found section start or end symbol, but not both: "
1656 "path=\"%s\", symbol-start=\"%s\", "
1657 "symbol-end=\"%s\", symbol-start-addr=%p, "
1658 "symbol-end-addr=%p",
1659 path
, "__bt_get_begin_section_component_class_descriptor_attributes",
1660 "__bt_get_end_section_component_class_descriptor_attributes",
1661 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1662 status
= BT_FUNC_STATUS_NOT_FOUND
;
1668 /* Initialize plugin */
1669 BT_LOGD_STR("Initializing plugin object.");
1670 status
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
1672 descriptors_begin
, descriptors_end
, attrs_begin
, attrs_end
,
1673 cc_descriptors_begin
, cc_descriptors_end
,
1674 cc_descr_attrs_begin
, cc_descr_attrs_end
, plugin_set_out
);
1677 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle
);
1682 void plugin_comp_class_destroy_listener(struct bt_component_class
*comp_class
,
1685 bt_list_del(&comp_class
->node
);
1686 BT_OBJECT_PUT_REF_AND_RESET(comp_class
->so_handle
);
1687 BT_LOGD("Component class destroyed: removed entry from list: "
1688 "comp-cls-addr=%p", comp_class
);
1691 void bt_plugin_so_on_add_component_class(struct bt_plugin
*plugin
,
1692 struct bt_component_class
*comp_class
)
1694 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
1696 BT_ASSERT(plugin
->spec_data
);
1697 BT_ASSERT(plugin
->type
== BT_PLUGIN_TYPE_SO
);
1699 bt_list_add(&comp_class
->node
, &component_class_list
);
1700 comp_class
->so_handle
= spec
->shared_lib_handle
;
1701 bt_object_get_ref_no_null_check(comp_class
->so_handle
);
1703 /* Add our custom destroy listener */
1704 bt_component_class_add_destroy_listener(comp_class
,
1705 plugin_comp_class_destroy_listener
, NULL
);