2 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
3 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 #define BT_LOG_TAG "LIB/PLUGIN-SO"
27 #include "lib/logging.h"
29 #include "common/assert.h"
30 #include "lib/assert-pre.h"
31 #include "compat/compiler.h"
32 #include <babeltrace2/plugin/plugin-dev.h>
33 #include "lib/graph/component-class.h"
34 #include <babeltrace2/graph/component-class.h>
35 #include <babeltrace2/graph/component-class-source.h>
36 #include <babeltrace2/graph/component-class-filter.h>
37 #include <babeltrace2/graph/component-class-sink.h>
38 #include <babeltrace2/types.h>
39 #include "common/list.h"
46 #include "plugin-so.h"
47 #include "lib/func-status.h"
48 #include "common/common.h"
50 #define NATIVE_PLUGIN_SUFFIX "." G_MODULE_SUFFIX
51 #define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
52 #define LIBTOOL_PLUGIN_SUFFIX ".la"
53 #define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
55 #define PLUGIN_SUFFIX_LEN bt_max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
56 sizeof(LIBTOOL_PLUGIN_SUFFIX))
61 * This list, global to the library, keeps all component classes that
62 * have a reference to their shared library handles. It allows iteration
63 * on all component classes still present when the destructor executes
64 * to release the shared library handle references they might still have.
66 * The list items are the component classes created with
67 * bt_plugin_add_component_class(). They keep the shared library handle
68 * object created by their plugin alive so that the plugin's code is
69 * not discarded when it could still be in use by living components
70 * created from those component classes:
72 * [component] --ref-> [component class]-> [shlib handle]
74 * It allows this use-case:
76 * my_plugins = bt_plugin_find_all_from_file("/path/to/my-plugin.so");
77 * // instantiate components from a plugin's component classes
78 * // put plugins and free my_plugins here
79 * // user code of instantiated components still exists
81 * An entry is removed from this list when a component class is
82 * destroyed thanks to a custom destroy listener. When the entry is
83 * removed, the entry is removed from the list, and we release the
84 * reference on the shlib handle. Assuming the original plugin object
85 * which contained some component classes is put first, when the last
86 * component class is removed from this list, the shared library handle
87 * object's reference count falls to zero and the shared library is
92 BT_LIST_HEAD(component_class_list
);
94 __attribute__((destructor
)) static
95 void fini_comp_class_list(void)
97 struct bt_component_class
*comp_class
, *tmp
;
99 bt_list_for_each_entry_safe(comp_class
, tmp
, &component_class_list
, node
) {
100 bt_list_del(&comp_class
->node
);
101 BT_OBJECT_PUT_REF_AND_RESET(comp_class
->so_handle
);
104 BT_LOGD_STR("Released references from all component classes to shared library handles.");
108 void bt_plugin_so_shared_lib_handle_destroy(struct bt_object
*obj
)
110 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
;
113 shared_lib_handle
= container_of(obj
,
114 struct bt_plugin_so_shared_lib_handle
, base
);
115 const char *path
= shared_lib_handle
->path
?
116 shared_lib_handle
->path
->str
: NULL
;
118 BT_LOGI("Destroying shared library handle: addr=%p, path=\"%s\"",
119 shared_lib_handle
, path
);
121 if (shared_lib_handle
->init_called
&& shared_lib_handle
->exit
) {
122 BT_LOGD_STR("Calling user's plugin exit function.");
123 shared_lib_handle
->exit();
124 BT_LOGD_STR("User function returned.");
127 if (shared_lib_handle
->module
) {
128 #ifndef BT_DEBUG_MODE
130 * Valgrind shows incomplete stack traces when
131 * dynamically loaded libraries are closed before it
132 * finishes. Use the LIBBABELTRACE2_NO_DLCLOSE in a debug
133 * build to avoid this.
135 const char *var
= getenv("LIBBABELTRACE2_NO_DLCLOSE");
137 if (!var
|| strcmp(var
, "1") != 0) {
139 BT_LOGI("Closing GModule: path=\"%s\"", path
);
141 if (!g_module_close(shared_lib_handle
->module
)) {
142 BT_LOGE("Cannot close GModule: %s: path=\"%s\"",
143 g_module_error(), path
);
146 shared_lib_handle
->module
= NULL
;
147 #ifndef BT_DEBUG_MODE
149 BT_LOGI("Not closing GModule because `LIBBABELTRACE2_NO_DLCLOSE=1`: "
150 "path=\"%s\"", path
);
155 if (shared_lib_handle
->path
) {
156 g_string_free(shared_lib_handle
->path
, TRUE
);
157 shared_lib_handle
->path
= NULL
;
160 g_free(shared_lib_handle
);
164 int bt_plugin_so_shared_lib_handle_create(
166 struct bt_plugin_so_shared_lib_handle
**shared_lib_handle
)
168 int status
= BT_FUNC_STATUS_OK
;
170 BT_ASSERT(shared_lib_handle
);
171 BT_LOGI("Creating shared library handle: path=\"%s\"", path
);
172 *shared_lib_handle
= g_new0(struct bt_plugin_so_shared_lib_handle
, 1);
173 if (!*shared_lib_handle
) {
174 BT_LOGE_STR("Failed to allocate one shared library handle.");
175 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
179 bt_object_init_shared(&(*shared_lib_handle
)->base
,
180 bt_plugin_so_shared_lib_handle_destroy
);
186 (*shared_lib_handle
)->path
= g_string_new(path
);
187 if (!(*shared_lib_handle
)->path
) {
188 BT_LOGE_STR("Failed to allocate a GString.");
189 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
193 (*shared_lib_handle
)->module
= g_module_open(path
, G_MODULE_BIND_LOCAL
);
194 if (!(*shared_lib_handle
)->module
) {
196 * INFO-level logging because we're only _trying_ to
197 * open this file as a Babeltrace plugin: if it's not,
198 * it's not an error. And because this can be tried
199 * during bt_plugin_find_all_from_dir(), it's not even a
202 BT_LOGI("Cannot open GModule: %s: path=\"%s\"",
203 g_module_error(), path
);
204 BT_OBJECT_PUT_REF_AND_RESET(*shared_lib_handle
);
205 status
= BT_FUNC_STATUS_NOT_FOUND
;
212 BT_ASSERT(*shared_lib_handle
|| status
!= BT_FUNC_STATUS_OK
);
213 if (*shared_lib_handle
) {
214 BT_LOGI("Created shared library handle: path=\"%s\", addr=%p",
215 path
, *shared_lib_handle
);
222 void bt_plugin_so_destroy_spec_data(struct bt_plugin
*plugin
)
224 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
226 if (!plugin
->spec_data
) {
230 BT_ASSERT(plugin
->type
== BT_PLUGIN_TYPE_SO
);
232 BT_OBJECT_PUT_REF_AND_RESET(spec
->shared_lib_handle
);
233 g_free(plugin
->spec_data
);
234 plugin
->spec_data
= NULL
;
238 * This function does the following:
240 * 1. Iterate on the plugin descriptor attributes section and set the
241 * plugin's attributes depending on the attribute types. This
242 * includes the name of the plugin, its description, and its
243 * initialization function, for example.
245 * 2. Iterate on the component class descriptors section and create one
246 * "full descriptor" (temporary structure) for each one that is found
247 * and attached to our plugin descriptor.
249 * 3. Iterate on the component class descriptor attributes section and
250 * set the corresponding full descriptor's attributes depending on
251 * the attribute types. This includes the description of the
252 * component class, as well as its initialization and destroy
255 * 4. Call the user's plugin initialization function, if any is
258 * 5. For each full component class descriptor, create a component class
259 * object, set its optional attributes, and add it to the plugin
262 * 6. Freeze the plugin object.
265 int bt_plugin_so_init(struct bt_plugin
*plugin
,
266 bool fail_on_load_error
,
267 const struct __bt_plugin_descriptor
*descriptor
,
268 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
269 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
270 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
271 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
272 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
273 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
)
276 * This structure's members point to the plugin's memory
279 struct comp_class_full_descriptor
{
280 const struct __bt_plugin_component_class_descriptor
*descriptor
;
281 const char *description
;
286 bt_component_class_source_init_method init
;
287 bt_component_class_source_finalize_method finalize
;
288 bt_component_class_source_query_method query
;
289 bt_component_class_source_output_port_connected_method output_port_connected
;
290 bt_component_class_source_message_iterator_init_method msg_iter_init
;
291 bt_component_class_source_message_iterator_finalize_method msg_iter_finalize
;
292 bt_component_class_source_message_iterator_seek_ns_from_origin_method msg_iter_seek_ns_from_origin
;
293 bt_component_class_source_message_iterator_seek_beginning_method msg_iter_seek_beginning
;
294 bt_component_class_source_message_iterator_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin
;
295 bt_component_class_source_message_iterator_can_seek_beginning_method msg_iter_can_seek_beginning
;
299 bt_component_class_filter_init_method init
;
300 bt_component_class_filter_finalize_method finalize
;
301 bt_component_class_filter_query_method query
;
302 bt_component_class_filter_input_port_connected_method input_port_connected
;
303 bt_component_class_filter_output_port_connected_method output_port_connected
;
304 bt_component_class_filter_message_iterator_init_method msg_iter_init
;
305 bt_component_class_filter_message_iterator_finalize_method msg_iter_finalize
;
306 bt_component_class_filter_message_iterator_seek_ns_from_origin_method msg_iter_seek_ns_from_origin
;
307 bt_component_class_filter_message_iterator_seek_beginning_method msg_iter_seek_beginning
;
308 bt_component_class_filter_message_iterator_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin
;
309 bt_component_class_filter_message_iterator_can_seek_beginning_method msg_iter_can_seek_beginning
;
313 bt_component_class_sink_init_method init
;
314 bt_component_class_sink_finalize_method finalize
;
315 bt_component_class_sink_query_method query
;
316 bt_component_class_sink_input_port_connected_method input_port_connected
;
317 bt_component_class_sink_graph_is_configured_method graph_is_configured
;
322 int status
= BT_FUNC_STATUS_OK
;
323 struct __bt_plugin_descriptor_attribute
const * const *cur_attr_ptr
;
324 struct __bt_plugin_component_class_descriptor
const * const *cur_cc_descr_ptr
;
325 struct __bt_plugin_component_class_descriptor_attribute
const * const *cur_cc_descr_attr_ptr
;
326 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
327 GArray
*comp_class_full_descriptors
;
331 BT_LOGI("Initializing plugin object from descriptors found in sections: "
332 "plugin-addr=%p, plugin-path=\"%s\", "
333 "attrs-begin-addr=%p, attrs-end-addr=%p, "
334 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
335 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p",
337 spec
->shared_lib_handle
->path
?
338 spec
->shared_lib_handle
->path
->str
: NULL
,
339 attrs_begin
, attrs_end
,
340 cc_descriptors_begin
, cc_descriptors_end
,
341 cc_descr_attrs_begin
, cc_descr_attrs_end
);
342 comp_class_full_descriptors
= g_array_new(FALSE
, TRUE
,
343 sizeof(struct comp_class_full_descriptor
));
344 if (!comp_class_full_descriptors
) {
345 BT_LOGE_STR("Failed to allocate a GArray.");
346 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
350 /* Set mandatory attributes */
351 spec
->descriptor
= descriptor
;
352 bt_plugin_set_name(plugin
, descriptor
->name
);
355 * Find and set optional attributes attached to this plugin
358 for (cur_attr_ptr
= attrs_begin
; cur_attr_ptr
!= attrs_end
; cur_attr_ptr
++) {
359 const struct __bt_plugin_descriptor_attribute
*cur_attr
=
362 if (cur_attr
== NULL
) {
366 if (cur_attr
->plugin_descriptor
!= descriptor
) {
370 switch (cur_attr
->type
) {
371 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT
:
372 spec
->init
= cur_attr
->value
.init
;
374 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT
:
375 spec
->shared_lib_handle
->exit
= cur_attr
->value
.exit
;
377 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR
:
378 bt_plugin_set_author(plugin
, cur_attr
->value
.author
);
380 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE
:
381 bt_plugin_set_license(plugin
, cur_attr
->value
.license
);
383 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
384 bt_plugin_set_description(plugin
, cur_attr
->value
.description
);
386 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION
:
387 bt_plugin_set_version(plugin
,
388 (unsigned int) cur_attr
->value
.version
.major
,
389 (unsigned int) cur_attr
->value
.version
.minor
,
390 (unsigned int) cur_attr
->value
.version
.patch
,
391 cur_attr
->value
.version
.extra
);
394 BT_LOG_WRITE(fail_on_load_error
?
395 BT_LOG_WARN
: BT_LOG_INFO
, BT_LOG_TAG
,
396 "%s plugin descriptor attribute: "
397 "plugin-path=\"%s\", plugin-name=\"%s\", "
398 "attr-type-name=\"%s\", attr-type-id=%d",
399 fail_on_load_error
? "Unknown" :
401 spec
->shared_lib_handle
->path
?
402 spec
->shared_lib_handle
->path
->str
:
404 descriptor
->name
, cur_attr
->type_name
,
407 if (fail_on_load_error
) {
408 status
= BT_FUNC_STATUS_LOADING_ERROR
;
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};
426 if (cur_cc_descr
== NULL
) {
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
== NULL
) {
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_INIT_METHOD
:
482 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
483 cc_full_descr
->methods
.source
.init
=
484 cur_cc_descr_attr
->value
.source_init_method
;
486 case BT_COMPONENT_CLASS_TYPE_FILTER
:
487 cc_full_descr
->methods
.filter
.init
=
488 cur_cc_descr_attr
->value
.filter_init_method
;
490 case BT_COMPONENT_CLASS_TYPE_SINK
:
491 cc_full_descr
->methods
.sink
.init
=
492 cur_cc_descr_attr
->value
.sink_init_method
;
498 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD
:
500 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
501 cc_full_descr
->methods
.source
.finalize
=
502 cur_cc_descr_attr
->value
.source_finalize_method
;
504 case BT_COMPONENT_CLASS_TYPE_FILTER
:
505 cc_full_descr
->methods
.filter
.finalize
=
506 cur_cc_descr_attr
->value
.filter_finalize_method
;
508 case BT_COMPONENT_CLASS_TYPE_SINK
:
509 cc_full_descr
->methods
.sink
.finalize
=
510 cur_cc_descr_attr
->value
.sink_finalize_method
;
516 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD
:
518 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
519 cc_full_descr
->methods
.source
.query
=
520 cur_cc_descr_attr
->value
.source_query_method
;
522 case BT_COMPONENT_CLASS_TYPE_FILTER
:
523 cc_full_descr
->methods
.filter
.query
=
524 cur_cc_descr_attr
->value
.filter_query_method
;
526 case BT_COMPONENT_CLASS_TYPE_SINK
:
527 cc_full_descr
->methods
.sink
.query
=
528 cur_cc_descr_attr
->value
.sink_query_method
;
534 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INPUT_PORT_CONNECTED_METHOD
:
536 case BT_COMPONENT_CLASS_TYPE_FILTER
:
537 cc_full_descr
->methods
.filter
.input_port_connected
=
538 cur_cc_descr_attr
->value
.filter_input_port_connected_method
;
540 case BT_COMPONENT_CLASS_TYPE_SINK
:
541 cc_full_descr
->methods
.sink
.input_port_connected
=
542 cur_cc_descr_attr
->value
.sink_input_port_connected_method
;
548 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_OUTPUT_PORT_CONNECTED_METHOD
:
550 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
551 cc_full_descr
->methods
.source
.output_port_connected
=
552 cur_cc_descr_attr
->value
.source_output_port_connected_method
;
554 case BT_COMPONENT_CLASS_TYPE_FILTER
:
555 cc_full_descr
->methods
.filter
.output_port_connected
=
556 cur_cc_descr_attr
->value
.filter_output_port_connected_method
;
562 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GRAPH_IS_CONFIGURED_METHOD
:
564 case BT_COMPONENT_CLASS_TYPE_SINK
:
565 cc_full_descr
->methods
.sink
.graph_is_configured
=
566 cur_cc_descr_attr
->value
.sink_graph_is_configured_method
;
572 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_INIT_METHOD
:
574 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
575 cc_full_descr
->methods
.source
.msg_iter_init
=
576 cur_cc_descr_attr
->value
.source_msg_iter_init_method
;
578 case BT_COMPONENT_CLASS_TYPE_FILTER
:
579 cc_full_descr
->methods
.filter
.msg_iter_init
=
580 cur_cc_descr_attr
->value
.filter_msg_iter_init_method
;
586 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_FINALIZE_METHOD
:
588 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
589 cc_full_descr
->methods
.source
.msg_iter_finalize
=
590 cur_cc_descr_attr
->value
.source_msg_iter_finalize_method
;
592 case BT_COMPONENT_CLASS_TYPE_FILTER
:
593 cc_full_descr
->methods
.filter
.msg_iter_finalize
=
594 cur_cc_descr_attr
->value
.filter_msg_iter_finalize_method
;
600 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_NS_FROM_ORIGIN_METHOD
:
602 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
603 cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
=
604 cur_cc_descr_attr
->value
.source_msg_iter_seek_ns_from_origin_method
;
606 case BT_COMPONENT_CLASS_TYPE_FILTER
:
607 cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
=
608 cur_cc_descr_attr
->value
.filter_msg_iter_seek_ns_from_origin_method
;
614 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_BEGINNING_METHOD
:
616 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
617 cc_full_descr
->methods
.source
.msg_iter_seek_beginning
=
618 cur_cc_descr_attr
->value
.source_msg_iter_seek_beginning_method
;
620 case BT_COMPONENT_CLASS_TYPE_FILTER
:
621 cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
=
622 cur_cc_descr_attr
->value
.filter_msg_iter_seek_beginning_method
;
628 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_NS_FROM_ORIGIN_METHOD
:
630 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
631 cc_full_descr
->methods
.source
.msg_iter_can_seek_ns_from_origin
=
632 cur_cc_descr_attr
->value
.source_msg_iter_can_seek_ns_from_origin_method
;
634 case BT_COMPONENT_CLASS_TYPE_FILTER
:
635 cc_full_descr
->methods
.filter
.msg_iter_can_seek_ns_from_origin
=
636 cur_cc_descr_attr
->value
.filter_msg_iter_can_seek_ns_from_origin_method
;
642 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_BEGINNING_METHOD
:
644 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
645 cc_full_descr
->methods
.source
.msg_iter_can_seek_beginning
=
646 cur_cc_descr_attr
->value
.source_msg_iter_can_seek_beginning_method
;
648 case BT_COMPONENT_CLASS_TYPE_FILTER
:
649 cc_full_descr
->methods
.filter
.msg_iter_can_seek_beginning
=
650 cur_cc_descr_attr
->value
.filter_msg_iter_can_seek_beginning_method
;
657 BT_LOG_WRITE(fail_on_load_error
?
658 BT_LOG_WARN
: BT_LOG_INFO
, BT_LOG_TAG
,
659 "%s component class descriptor attribute: "
660 "plugin-path=\"%s\", "
661 "plugin-name=\"%s\", "
662 "comp-class-name=\"%s\", "
663 "comp-class-type=%s, "
664 "attr-type-name=\"%s\", "
666 fail_on_load_error
? "Unknown" :
668 spec
->shared_lib_handle
->path
?
669 spec
->shared_lib_handle
->path
->str
:
672 cur_cc_descr_attr
->comp_class_descriptor
->name
,
673 bt_component_class_type_string(
674 cur_cc_descr_attr
->comp_class_descriptor
->type
),
675 cur_cc_descr_attr
->type_name
,
676 cur_cc_descr_attr
->type
);
678 if (fail_on_load_error
) {
679 status
= BT_FUNC_STATUS_LOADING_ERROR
;
688 /* Initialize plugin */
690 enum bt_plugin_init_func_status init_status
;
692 BT_LOGD_STR("Calling user's plugin initialization function.");
693 init_status
= spec
->init((void *) plugin
);
694 BT_LOGD("User function returned: status=%s",
695 bt_common_func_status_string(init_status
));
697 if (init_status
< 0) {
698 BT_LOG_WRITE(fail_on_load_error
?
699 BT_LOG_WARN
: BT_LOG_INFO
, BT_LOG_TAG
,
700 "User's plugin initialization function failed: "
702 bt_common_func_status_string(init_status
));
704 if (fail_on_load_error
) {
705 status
= init_status
;
711 spec
->shared_lib_handle
->init_called
= BT_TRUE
;
713 /* Add described component classes to plugin */
714 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
715 struct comp_class_full_descriptor
*cc_full_descr
=
716 &g_array_index(comp_class_full_descriptors
,
717 struct comp_class_full_descriptor
, i
);
718 struct bt_component_class
*comp_class
= NULL
;
719 struct bt_component_class_source
*src_comp_class
= NULL
;
720 struct bt_component_class_filter
*flt_comp_class
= NULL
;
721 struct bt_component_class_sink
*sink_comp_class
= NULL
;
723 BT_LOGI("Creating and setting properties of plugin's component class: "
724 "plugin-path=\"%s\", plugin-name=\"%s\", "
725 "comp-class-name=\"%s\", comp-class-type=%s",
726 spec
->shared_lib_handle
->path
?
727 spec
->shared_lib_handle
->path
->str
:
730 cc_full_descr
->descriptor
->name
,
731 bt_component_class_type_string(
732 cc_full_descr
->descriptor
->type
));
734 switch (cc_full_descr
->descriptor
->type
) {
735 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
736 src_comp_class
= bt_component_class_source_create(
737 cc_full_descr
->descriptor
->name
,
738 cc_full_descr
->descriptor
->methods
.source
.msg_iter_next
);
739 comp_class
= bt_component_class_source_as_component_class(
742 case BT_COMPONENT_CLASS_TYPE_FILTER
:
743 flt_comp_class
= bt_component_class_filter_create(
744 cc_full_descr
->descriptor
->name
,
745 cc_full_descr
->descriptor
->methods
.source
.msg_iter_next
);
746 comp_class
= bt_component_class_filter_as_component_class(
749 case BT_COMPONENT_CLASS_TYPE_SINK
:
750 sink_comp_class
= bt_component_class_sink_create(
751 cc_full_descr
->descriptor
->name
,
752 cc_full_descr
->descriptor
->methods
.sink
.consume
);
753 comp_class
= bt_component_class_sink_as_component_class(
757 BT_LOG_WRITE(fail_on_load_error
?
758 BT_LOG_WARN
: BT_LOG_INFO
, BT_LOG_TAG
,
759 "%s component class type: "
760 "plugin-path=\"%s\", plugin-name=\"%s\", "
761 "comp-class-name=\"%s\", comp-class-type=%d",
762 fail_on_load_error
? "Unknown" :
764 spec
->shared_lib_handle
->path
->str
?
765 spec
->shared_lib_handle
->path
->str
:
768 cc_full_descr
->descriptor
->name
,
769 cc_full_descr
->descriptor
->type
);
771 if (fail_on_load_error
) {
772 status
= BT_FUNC_STATUS_LOADING_ERROR
;
780 BT_LOGE_STR("Cannot create component class.");
781 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
785 if (cc_full_descr
->description
) {
786 ret
= bt_component_class_set_description(
787 comp_class
, cc_full_descr
->description
);
789 BT_LOGE_STR("Cannot set component class's description.");
790 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
791 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
796 if (cc_full_descr
->help
) {
797 ret
= bt_component_class_set_help(comp_class
,
798 cc_full_descr
->help
);
800 BT_LOGE_STR("Cannot set component class's help string.");
801 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
802 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
807 switch (cc_full_descr
->descriptor
->type
) {
808 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
809 if (cc_full_descr
->methods
.source
.init
) {
810 ret
= bt_component_class_source_set_init_method(
812 cc_full_descr
->methods
.source
.init
);
814 BT_LOGE_STR("Cannot set source component class's initialization method.");
815 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
816 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
821 if (cc_full_descr
->methods
.source
.finalize
) {
822 ret
= bt_component_class_source_set_finalize_method(
824 cc_full_descr
->methods
.source
.finalize
);
826 BT_LOGE_STR("Cannot set source component class's finalization method.");
827 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
828 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
833 if (cc_full_descr
->methods
.source
.query
) {
834 ret
= bt_component_class_source_set_query_method(
836 cc_full_descr
->methods
.source
.query
);
838 BT_LOGE_STR("Cannot set source component class's query method.");
839 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
840 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
845 if (cc_full_descr
->methods
.source
.output_port_connected
) {
846 ret
= bt_component_class_source_set_output_port_connected_method(
848 cc_full_descr
->methods
.source
.output_port_connected
);
850 BT_LOGE_STR("Cannot set source component class's \"output port connected\" method.");
851 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
852 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
857 if (cc_full_descr
->methods
.source
.msg_iter_init
) {
858 ret
= bt_component_class_source_set_message_iterator_init_method(
860 cc_full_descr
->methods
.source
.msg_iter_init
);
862 BT_LOGE_STR("Cannot set source component class's message iterator initialization method.");
863 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
864 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
869 if (cc_full_descr
->methods
.source
.msg_iter_finalize
) {
870 ret
= bt_component_class_source_set_message_iterator_finalize_method(
872 cc_full_descr
->methods
.source
.msg_iter_finalize
);
874 BT_LOGE_STR("Cannot set source component class's message iterator finalization method.");
875 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
876 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
881 if (cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
) {
882 ret
= bt_component_class_source_set_message_iterator_seek_ns_from_origin_method(
884 cc_full_descr
->methods
.source
.msg_iter_seek_ns_from_origin
);
886 BT_LOGE_STR("Cannot set source component class's message iterator \"seek nanoseconds from origin\" method.");
887 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
888 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
893 if (cc_full_descr
->methods
.source
.msg_iter_seek_beginning
) {
894 ret
= bt_component_class_source_set_message_iterator_seek_beginning_method(
896 cc_full_descr
->methods
.source
.msg_iter_seek_beginning
);
898 BT_LOGE_STR("Cannot set source component class's message iterator \"seek beginning\" method.");
899 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
900 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
905 if (cc_full_descr
->methods
.source
.msg_iter_can_seek_ns_from_origin
) {
906 ret
= bt_component_class_source_set_message_iterator_can_seek_ns_from_origin_method(
908 cc_full_descr
->methods
.source
.msg_iter_can_seek_ns_from_origin
);
910 BT_LOGE_STR("Cannot set source component class's message iterator \"can seek nanoseconds from origin\" method.");
911 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
912 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
917 if (cc_full_descr
->methods
.source
.msg_iter_can_seek_beginning
) {
918 ret
= bt_component_class_source_set_message_iterator_can_seek_beginning_method(
920 cc_full_descr
->methods
.source
.msg_iter_can_seek_beginning
);
922 BT_LOGE_STR("Cannot set source component class's message iterator \"can seek beginning\" method.");
923 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
924 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class
);
930 case BT_COMPONENT_CLASS_TYPE_FILTER
:
931 if (cc_full_descr
->methods
.filter
.init
) {
932 ret
= bt_component_class_filter_set_init_method(
934 cc_full_descr
->methods
.filter
.init
);
936 BT_LOGE_STR("Cannot set filter component class's initialization method.");
937 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
938 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
943 if (cc_full_descr
->methods
.filter
.finalize
) {
944 ret
= bt_component_class_filter_set_finalize_method(
946 cc_full_descr
->methods
.filter
.finalize
);
948 BT_LOGE_STR("Cannot set filter component class's finalization method.");
949 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
950 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
955 if (cc_full_descr
->methods
.filter
.query
) {
956 ret
= bt_component_class_filter_set_query_method(
958 cc_full_descr
->methods
.filter
.query
);
960 BT_LOGE_STR("Cannot set filter component class's query method.");
961 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
962 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
967 if (cc_full_descr
->methods
.filter
.input_port_connected
) {
968 ret
= bt_component_class_filter_set_input_port_connected_method(
970 cc_full_descr
->methods
.filter
.input_port_connected
);
972 BT_LOGE_STR("Cannot set filter component class's \"input port connected\" method.");
973 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
974 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
979 if (cc_full_descr
->methods
.filter
.output_port_connected
) {
980 ret
= bt_component_class_filter_set_output_port_connected_method(
982 cc_full_descr
->methods
.filter
.output_port_connected
);
984 BT_LOGE_STR("Cannot set filter component class's \"output port connected\" method.");
985 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
986 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
991 if (cc_full_descr
->methods
.filter
.msg_iter_init
) {
992 ret
= bt_component_class_filter_set_message_iterator_init_method(
994 cc_full_descr
->methods
.filter
.msg_iter_init
);
996 BT_LOGE_STR("Cannot set filter component class's message iterator initialization method.");
997 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
998 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1003 if (cc_full_descr
->methods
.filter
.msg_iter_finalize
) {
1004 ret
= bt_component_class_filter_set_message_iterator_finalize_method(
1006 cc_full_descr
->methods
.filter
.msg_iter_finalize
);
1008 BT_LOGE_STR("Cannot set filter component class's message iterator finalization method.");
1009 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1010 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1015 if (cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
) {
1016 ret
= bt_component_class_filter_set_message_iterator_seek_ns_from_origin_method(
1018 cc_full_descr
->methods
.filter
.msg_iter_seek_ns_from_origin
);
1020 BT_LOGE_STR("Cannot set filter component class's message iterator \"seek nanoseconds from origin\" method.");
1021 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1022 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1027 if (cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
) {
1028 ret
= bt_component_class_filter_set_message_iterator_seek_beginning_method(
1030 cc_full_descr
->methods
.filter
.msg_iter_seek_beginning
);
1032 BT_LOGE_STR("Cannot set filter component class's message iterator \"seek beginning\" method.");
1033 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1034 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1039 if (cc_full_descr
->methods
.filter
.msg_iter_can_seek_ns_from_origin
) {
1040 ret
= bt_component_class_filter_set_message_iterator_can_seek_ns_from_origin_method(
1042 cc_full_descr
->methods
.filter
.msg_iter_can_seek_ns_from_origin
);
1044 BT_LOGE_STR("Cannot set filter component class's message iterator \"can seek nanoseconds from origin\" method.");
1045 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1046 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1051 if (cc_full_descr
->methods
.filter
.msg_iter_can_seek_beginning
) {
1052 ret
= bt_component_class_filter_set_message_iterator_can_seek_beginning_method(
1054 cc_full_descr
->methods
.filter
.msg_iter_can_seek_beginning
);
1056 BT_LOGE_STR("Cannot set filter component class's message iterator \"can seek beginning\" method.");
1057 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1058 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class
);
1064 case BT_COMPONENT_CLASS_TYPE_SINK
:
1065 if (cc_full_descr
->methods
.sink
.init
) {
1066 ret
= bt_component_class_sink_set_init_method(
1068 cc_full_descr
->methods
.sink
.init
);
1070 BT_LOGE_STR("Cannot set sink component class's initialization method.");
1071 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1072 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1077 if (cc_full_descr
->methods
.sink
.finalize
) {
1078 ret
= bt_component_class_sink_set_finalize_method(
1080 cc_full_descr
->methods
.sink
.finalize
);
1082 BT_LOGE_STR("Cannot set sink component class's finalization method.");
1083 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1084 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1089 if (cc_full_descr
->methods
.sink
.query
) {
1090 ret
= bt_component_class_sink_set_query_method(
1092 cc_full_descr
->methods
.sink
.query
);
1094 BT_LOGE_STR("Cannot set sink component class's query method.");
1095 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1096 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1101 if (cc_full_descr
->methods
.sink
.input_port_connected
) {
1102 ret
= bt_component_class_sink_set_input_port_connected_method(
1104 cc_full_descr
->methods
.sink
.input_port_connected
);
1106 BT_LOGE_STR("Cannot set sink component class's \"input port connected\" method.");
1107 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1108 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1113 if (cc_full_descr
->methods
.sink
.graph_is_configured
) {
1114 ret
= bt_component_class_sink_set_graph_is_configured_method(
1116 cc_full_descr
->methods
.sink
.graph_is_configured
);
1118 BT_LOGE_STR("Cannot set sink component class's \"graph is configured\" method.");
1119 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1120 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class
);
1131 * Add component class to the plugin object.
1133 * This will call back
1134 * bt_plugin_so_on_add_component_class() so that we can
1135 * add a mapping in the component class list when we
1136 * know the component class is successfully added.
1138 status
= bt_plugin_add_component_class(plugin
,
1139 (void *) comp_class
);
1140 BT_OBJECT_PUT_REF_AND_RESET(comp_class
);
1142 BT_LOGE("Cannot add component class to plugin.");
1148 g_array_free(comp_class_full_descriptors
, TRUE
);
1153 struct bt_plugin
*bt_plugin_so_create_empty(
1154 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
)
1156 struct bt_plugin
*plugin
;
1157 struct bt_plugin_so_spec_data
*spec
;
1159 plugin
= bt_plugin_create_empty(BT_PLUGIN_TYPE_SO
);
1164 plugin
->destroy_spec_data
= bt_plugin_so_destroy_spec_data
;
1165 plugin
->spec_data
= g_new0(struct bt_plugin_so_spec_data
, 1);
1166 if (!plugin
->spec_data
) {
1167 BT_LOGE_STR("Failed to allocate one SO plugin specific data structure.");
1171 spec
= plugin
->spec_data
;
1172 spec
->shared_lib_handle
= shared_lib_handle
;
1173 bt_object_get_no_null_check(spec
->shared_lib_handle
);
1177 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1184 size_t count_non_null_items_in_section(const void *begin
, const void *end
)
1187 const int * const *begin_int
= (const int * const *) begin
;
1188 const int * const *end_int
= (const int * const *) end
;
1189 const int * const *iter
;
1191 for (iter
= begin_int
; iter
!= end_int
; iter
++) {
1201 int bt_plugin_so_create_all_from_sections(
1202 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
,
1203 bool fail_on_load_error
,
1204 struct __bt_plugin_descriptor
const * const *descriptors_begin
,
1205 struct __bt_plugin_descriptor
const * const *descriptors_end
,
1206 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
1207 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
1208 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
1209 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
1210 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
1211 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
,
1212 struct bt_plugin_set
**plugin_set_out
)
1214 int status
= BT_FUNC_STATUS_OK
;
1215 size_t descriptor_count
;
1217 size_t cc_descriptors_count
;
1218 size_t cc_descr_attrs_count
;
1221 BT_ASSERT(plugin_set_out
);
1222 *plugin_set_out
= NULL
;
1223 descriptor_count
= count_non_null_items_in_section(descriptors_begin
, descriptors_end
);
1224 attrs_count
= count_non_null_items_in_section(attrs_begin
, attrs_end
);
1225 cc_descriptors_count
= count_non_null_items_in_section(cc_descriptors_begin
, cc_descriptors_end
);
1226 cc_descr_attrs_count
= count_non_null_items_in_section(cc_descr_attrs_begin
, cc_descr_attrs_end
);
1227 BT_LOGI("Creating all SO plugins from sections: "
1228 "plugin-path=\"%s\", "
1229 "descr-begin-addr=%p, descr-end-addr=%p, "
1230 "attrs-begin-addr=%p, attrs-end-addr=%p, "
1231 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
1232 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p, "
1233 "descr-count=%zu, attrs-count=%zu, "
1234 "cc-descr-count=%zu, cc-descr-attrs-count=%zu",
1235 shared_lib_handle
->path
? shared_lib_handle
->path
->str
: NULL
,
1236 descriptors_begin
, descriptors_end
,
1237 attrs_begin
, attrs_end
,
1238 cc_descriptors_begin
, cc_descriptors_end
,
1239 cc_descr_attrs_begin
, cc_descr_attrs_end
,
1240 descriptor_count
, attrs_count
,
1241 cc_descriptors_count
, cc_descr_attrs_count
);
1242 *plugin_set_out
= bt_plugin_set_create();
1243 if (!*plugin_set_out
) {
1244 BT_LOGE_STR("Cannot create empty plugin set.");
1245 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1249 for (i
= 0; i
< descriptors_end
- descriptors_begin
; i
++) {
1250 const struct __bt_plugin_descriptor
*descriptor
=
1251 descriptors_begin
[i
];
1252 struct bt_plugin
*plugin
;
1254 if (descriptor
== NULL
) {
1258 BT_LOGI("Creating plugin object for plugin: "
1259 "name=\"%s\", abi-major=%d, abi-minor=%d",
1260 descriptor
->name
, descriptor
->major
, descriptor
->minor
);
1262 if (descriptor
->major
> __BT_PLUGIN_VERSION_MAJOR
) {
1263 BT_LOG_WRITE(fail_on_load_error
? BT_LOG_WARN
:
1264 BT_LOG_INFO
, BT_LOG_TAG
,
1265 "Unknown ABI major version: abi-major=%d",
1268 if (fail_on_load_error
) {
1269 status
= BT_FUNC_STATUS_LOADING_ERROR
;
1276 plugin
= bt_plugin_so_create_empty(shared_lib_handle
);
1278 BT_LOGE_STR("Cannot create empty shared library handle.");
1279 status
= BT_FUNC_STATUS_MEMORY_ERROR
;
1283 if (shared_lib_handle
&& shared_lib_handle
->path
) {
1284 bt_plugin_set_path(plugin
,
1285 shared_lib_handle
->path
->str
);
1288 status
= bt_plugin_so_init(plugin
, fail_on_load_error
,
1289 descriptor
, attrs_begin
, attrs_end
,
1290 cc_descriptors_begin
, cc_descriptors_end
,
1291 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1292 if (status
== BT_FUNC_STATUS_OK
) {
1293 /* Add to plugin set */
1294 bt_plugin_set_add_plugin(*plugin_set_out
, plugin
);
1295 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1296 } else if (status
< 0) {
1298 * bt_plugin_so_init() handles
1299 * `fail_on_load_error`, so this is a "real"
1302 BT_LOGW_STR("Cannot initialize SO plugin object from sections.");
1303 BT_OBJECT_PUT_REF_AND_RESET(plugin
);
1310 BT_ASSERT(*plugin_set_out
);
1312 if ((*plugin_set_out
)->plugins
->len
== 0) {
1313 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out
);
1314 status
= BT_FUNC_STATUS_NOT_FOUND
;
1320 BT_ASSERT(status
< 0);
1321 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out
);
1328 int bt_plugin_so_create_all_from_static(bool fail_on_load_error
,
1329 struct bt_plugin_set
**plugin_set_out
)
1332 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
1334 BT_ASSERT(plugin_set_out
);
1335 *plugin_set_out
= NULL
;
1336 status
= bt_plugin_so_shared_lib_handle_create(NULL
,
1337 &shared_lib_handle
);
1338 if (status
!= BT_FUNC_STATUS_OK
) {
1339 BT_ASSERT(!shared_lib_handle
);
1343 BT_ASSERT(shared_lib_handle
);
1344 BT_LOGD_STR("Creating all SO plugins from built-in plugins.");
1345 status
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
1347 __bt_get_begin_section_plugin_descriptors(),
1348 __bt_get_end_section_plugin_descriptors(),
1349 __bt_get_begin_section_plugin_descriptor_attributes(),
1350 __bt_get_end_section_plugin_descriptor_attributes(),
1351 __bt_get_begin_section_component_class_descriptors(),
1352 __bt_get_end_section_component_class_descriptors(),
1353 __bt_get_begin_section_component_class_descriptor_attributes(),
1354 __bt_get_end_section_component_class_descriptor_attributes(),
1356 BT_ASSERT((status
== BT_FUNC_STATUS_OK
&& *plugin_set_out
&&
1357 (*plugin_set_out
)->plugins
->len
> 0) || !*plugin_set_out
);
1360 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle
);
1365 int bt_plugin_so_create_all_from_file(const char *path
,
1366 bool fail_on_load_error
, struct bt_plugin_set
**plugin_set_out
)
1370 struct __bt_plugin_descriptor
const * const *descriptors_begin
= NULL
;
1371 struct __bt_plugin_descriptor
const * const *descriptors_end
= NULL
;
1372 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
= NULL
;
1373 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
= NULL
;
1374 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
= NULL
;
1375 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
= NULL
;
1376 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
= NULL
;
1377 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
= NULL
;
1378 struct __bt_plugin_descriptor
const * const *(*get_begin_section_plugin_descriptors
)(void);
1379 struct __bt_plugin_descriptor
const * const *(*get_end_section_plugin_descriptors
)(void);
1380 struct __bt_plugin_descriptor_attribute
const * const *(*get_begin_section_plugin_descriptor_attributes
)(void);
1381 struct __bt_plugin_descriptor_attribute
const * const *(*get_end_section_plugin_descriptor_attributes
)(void);
1382 struct __bt_plugin_component_class_descriptor
const * const *(*get_begin_section_component_class_descriptors
)(void);
1383 struct __bt_plugin_component_class_descriptor
const * const *(*get_end_section_component_class_descriptors
)(void);
1384 struct __bt_plugin_component_class_descriptor_attribute
const * const *(*get_begin_section_component_class_descriptor_attributes
)(void);
1385 struct __bt_plugin_component_class_descriptor_attribute
const * const *(*get_end_section_component_class_descriptor_attributes
)(void);
1386 bt_bool is_libtool_wrapper
= BT_FALSE
, is_shared_object
= BT_FALSE
;
1387 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
1390 BT_ASSERT(plugin_set_out
);
1391 *plugin_set_out
= NULL
;
1392 path_len
= strlen(path
);
1393 BT_ASSERT_PRE(path_len
> PLUGIN_SUFFIX_LEN
,
1394 "Path length is too short: path-length=%zu, min-length=%zu",
1395 path_len
, PLUGIN_SUFFIX_LEN
);
1396 BT_LOGI("Trying to create all SO plugins from file: path=\"%s\"", path
);
1400 * Check if the file ends with a known plugin file type suffix
1401 * (i.e. .so or .la on Linux).
1403 is_libtool_wrapper
= !strncmp(LIBTOOL_PLUGIN_SUFFIX
,
1404 path
+ path_len
- LIBTOOL_PLUGIN_SUFFIX_LEN
,
1405 LIBTOOL_PLUGIN_SUFFIX_LEN
);
1406 is_shared_object
= !strncmp(NATIVE_PLUGIN_SUFFIX
,
1407 path
+ path_len
- NATIVE_PLUGIN_SUFFIX_LEN
,
1408 NATIVE_PLUGIN_SUFFIX_LEN
);
1409 if (!is_shared_object
&& !is_libtool_wrapper
) {
1410 /* Name indicates this is not a plugin file; not an error */
1411 BT_LOGI("File is not an SO plugin file: path=\"%s\"", path
);
1412 status
= BT_FUNC_STATUS_NOT_FOUND
;
1416 status
= bt_plugin_so_shared_lib_handle_create(path
,
1417 &shared_lib_handle
);
1418 if (status
!= BT_FUNC_STATUS_OK
) {
1419 /* bt_plugin_so_shared_lib_handle_create() logs more details */
1420 BT_ASSERT(!shared_lib_handle
);
1421 BT_LOGE_STR("Cannot create shared library handle.");
1425 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_plugin_descriptors",
1426 (gpointer
*) &get_begin_section_plugin_descriptors
)) {
1427 descriptors_begin
= get_begin_section_plugin_descriptors();
1430 * Use this first symbol to know whether or not this
1431 * shared object _looks like_ a Babeltrace plugin. Since
1432 * g_module_symbol() failed, assume that this is not a
1433 * Babeltrace plugin, so it's not an error.
1435 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1436 "symbol=\"%s\"", path
,
1437 "__bt_get_begin_section_plugin_descriptors");
1438 status
= BT_FUNC_STATUS_NOT_FOUND
;
1443 * If g_module_symbol() fails for any of the other symbols, fail
1444 * if `fail_on_load_error` is true.
1446 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_plugin_descriptors",
1447 (gpointer
*) &get_end_section_plugin_descriptors
)) {
1448 descriptors_end
= get_end_section_plugin_descriptors();
1450 BT_LOG_WRITE(fail_on_load_error
? BT_LOG_WARN
: BT_LOG_INFO
,
1452 "Cannot resolve plugin symbol: path=\"%s\", "
1453 "symbol=\"%s\"", path
,
1454 "__bt_get_end_section_plugin_descriptors");
1455 status
= fail_on_load_error
? BT_FUNC_STATUS_LOADING_ERROR
:
1456 BT_FUNC_STATUS_NOT_FOUND
;
1460 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_plugin_descriptor_attributes",
1461 (gpointer
*) &get_begin_section_plugin_descriptor_attributes
)) {
1462 attrs_begin
= get_begin_section_plugin_descriptor_attributes();
1464 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1465 "symbol=\"%s\"", path
,
1466 "__bt_get_begin_section_plugin_descriptor_attributes");
1469 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_plugin_descriptor_attributes",
1470 (gpointer
*) &get_end_section_plugin_descriptor_attributes
)) {
1471 attrs_end
= get_end_section_plugin_descriptor_attributes();
1473 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1474 "symbol=\"%s\"", path
,
1475 "__bt_get_end_section_plugin_descriptor_attributes");
1478 if ((!!attrs_begin
- !!attrs_end
) != 0) {
1479 BT_LOG_WRITE(fail_on_load_error
? BT_LOG_WARN
: BT_LOG_INFO
,
1481 "Found section start or end symbol, but not both: "
1482 "path=\"%s\", symbol-start=\"%s\", "
1483 "symbol-end=\"%s\", symbol-start-addr=%p, "
1484 "symbol-end-addr=%p",
1485 path
, "__bt_get_begin_section_plugin_descriptor_attributes",
1486 "__bt_get_end_section_plugin_descriptor_attributes",
1487 attrs_begin
, attrs_end
);
1488 status
= fail_on_load_error
? BT_FUNC_STATUS_LOADING_ERROR
:
1489 BT_FUNC_STATUS_NOT_FOUND
;
1493 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_component_class_descriptors",
1494 (gpointer
*) &get_begin_section_component_class_descriptors
)) {
1495 cc_descriptors_begin
= get_begin_section_component_class_descriptors();
1497 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1498 "symbol=\"%s\"", path
,
1499 "__bt_get_begin_section_component_class_descriptors");
1502 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_component_class_descriptors",
1503 (gpointer
*) &get_end_section_component_class_descriptors
)) {
1504 cc_descriptors_end
= get_end_section_component_class_descriptors();
1506 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1507 "symbol=\"%s\"", path
,
1508 "__bt_get_end_section_component_class_descriptors");
1511 if ((!!cc_descriptors_begin
- !!cc_descriptors_end
) != 0) {
1512 BT_LOG_WRITE(fail_on_load_error
? BT_LOG_WARN
: BT_LOG_INFO
,
1514 "Found section start or end symbol, but not both: "
1515 "path=\"%s\", symbol-start=\"%s\", "
1516 "symbol-end=\"%s\", symbol-start-addr=%p, "
1517 "symbol-end-addr=%p",
1518 path
, "__bt_get_begin_section_component_class_descriptors",
1519 "__bt_get_end_section_component_class_descriptors",
1520 cc_descriptors_begin
, cc_descriptors_end
);
1521 status
= fail_on_load_error
? BT_FUNC_STATUS_LOADING_ERROR
:
1522 BT_FUNC_STATUS_NOT_FOUND
;
1526 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_begin_section_component_class_descriptor_attributes",
1527 (gpointer
*) &get_begin_section_component_class_descriptor_attributes
)) {
1528 cc_descr_attrs_begin
= get_begin_section_component_class_descriptor_attributes();
1530 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1531 "symbol=\"%s\"", path
,
1532 "__bt_get_begin_section_component_class_descriptor_attributes");
1535 if (g_module_symbol(shared_lib_handle
->module
, "__bt_get_end_section_component_class_descriptor_attributes",
1536 (gpointer
*) &get_end_section_component_class_descriptor_attributes
)) {
1537 cc_descr_attrs_end
= get_end_section_component_class_descriptor_attributes();
1539 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1540 "symbol=\"%s\"", path
,
1541 "__bt_get_end_section_component_class_descriptor_attributes");
1544 if ((!!cc_descr_attrs_begin
- !!cc_descr_attrs_end
) != 0) {
1545 BT_LOG_WRITE(fail_on_load_error
? BT_LOG_WARN
: BT_LOG_INFO
,
1547 "Found section start or end symbol, but not both: "
1548 "path=\"%s\", symbol-start=\"%s\", "
1549 "symbol-end=\"%s\", symbol-start-addr=%p, "
1550 "symbol-end-addr=%p",
1551 path
, "__bt_get_begin_section_component_class_descriptor_attributes",
1552 "__bt_get_end_section_component_class_descriptor_attributes",
1553 cc_descr_attrs_begin
, cc_descr_attrs_end
);
1554 status
= fail_on_load_error
? BT_FUNC_STATUS_LOADING_ERROR
:
1555 BT_FUNC_STATUS_NOT_FOUND
;
1559 /* Initialize plugin */
1560 BT_LOGD_STR("Initializing plugin object.");
1561 status
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
1563 descriptors_begin
, descriptors_end
, attrs_begin
, attrs_end
,
1564 cc_descriptors_begin
, cc_descriptors_end
,
1565 cc_descr_attrs_begin
, cc_descr_attrs_end
, plugin_set_out
);
1568 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle
);
1573 void plugin_comp_class_destroy_listener(struct bt_component_class
*comp_class
,
1576 bt_list_del(&comp_class
->node
);
1577 BT_OBJECT_PUT_REF_AND_RESET(comp_class
->so_handle
);
1578 BT_LOGD("Component class destroyed: removed entry from list: "
1579 "comp-cls-addr=%p", comp_class
);
1582 void bt_plugin_so_on_add_component_class(struct bt_plugin
*plugin
,
1583 struct bt_component_class
*comp_class
)
1585 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
1587 BT_ASSERT(plugin
->spec_data
);
1588 BT_ASSERT(plugin
->type
== BT_PLUGIN_TYPE_SO
);
1590 bt_list_add(&comp_class
->node
, &component_class_list
);
1591 comp_class
->so_handle
= spec
->shared_lib_handle
;
1592 bt_object_get_no_null_check(comp_class
->so_handle
);
1594 /* Add our custom destroy listener */
1595 bt_component_class_add_destroy_listener(comp_class
,
1596 plugin_comp_class_destroy_listener
, NULL
);