4 * Babeltrace Plugin (shared object)
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 #include <babeltrace/compiler-internal.h>
31 #include <babeltrace/ref.h>
32 #include <babeltrace/plugin/plugin-internal.h>
33 #include <babeltrace/plugin/plugin-so-internal.h>
34 #include <babeltrace/plugin/plugin-dev.h>
35 #include <babeltrace/plugin/plugin-internal.h>
36 #include <babeltrace/graph/component-class-internal.h>
37 #include <babeltrace/types.h>
43 #define NATIVE_PLUGIN_SUFFIX ".so"
44 #define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
45 #define LIBTOOL_PLUGIN_SUFFIX ".la"
46 #define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
48 #define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
49 sizeof(LIBTOOL_PLUGIN_SUFFIX))
51 #define SECTION_BEGIN(_name) (&(__start_##_name))
52 #define SECTION_END(_name) (&(__stop_##_name))
53 #define SECTION_ELEMENT_COUNT(_name) (SECTION_END(_name) - SECTION_BEGIN(_name))
55 #define DECLARE_SECTION(_type, _name) \
56 extern _type __start_##_name __attribute((weak)); \
57 extern _type __stop_##_name __attribute((weak))
59 DECLARE_SECTION(struct __bt_plugin_descriptor
const *, __bt_plugin_descriptors
);
60 DECLARE_SECTION(struct __bt_plugin_descriptor_attribute
const *, __bt_plugin_descriptor_attributes
);
61 DECLARE_SECTION(struct __bt_plugin_component_class_descriptor
const *, __bt_plugin_component_class_descriptors
);
62 DECLARE_SECTION(struct __bt_plugin_component_class_descriptor_attribute
const *, __bt_plugin_component_class_descriptor_attributes
);
65 * This hash table, global to the library, maps component class pointers
66 * to shared library handles.
68 * The keys (component classes) are NOT owned by this hash table, whereas
69 * the values (shared library handles) are owned by this hash table.
71 * The keys are the component classes created with
72 * bt_plugin_add_component_class(). They keep the shared library handle
73 * object created by their plugin alive so that the plugin's code is
74 * not discarded when it could still be in use by living components
75 * created from those component classes:
77 * [component] --ref-> [component class] --through this HT-> [shlib handle]
79 * This hash table exists for two reasons:
81 * 1. To allow this application:
83 * my_plugins = bt_plugin_create_all_from_file("/path/to/my-plugin.so");
84 * // instantiate components from a plugin's component classes
85 * // put plugins and free my_plugins here
86 * // user code of instantiated components still exists
88 * 2. To decouple the plugin subsystem from the component subsystem:
89 * while plugins objects need to know component class objects, the
90 * opposite is not necessary, thus it makes no sense for a component
91 * class to keep a reference to the plugin object from which it was
94 * An entry is removed from this HT when a component class is destroyed
95 * thanks to a custom destroy listener. When the entry is removed, the
96 * GLib function calls the value destroy notifier of the HT, which is
97 * bt_put(). This decreases the reference count of the mapped shared
98 * library handle. Assuming the original plugin object which contained
99 * some component classes is put first, when the last component class is
100 * removed from this HT, the shared library handle object's reference
101 * count falls to zero and the shared library is finally closed.
104 GHashTable
*comp_classes_to_shlib_handles
;
106 __attribute__((constructor
)) static
107 void init_comp_classes_to_shlib_handles(void) {
108 comp_classes_to_shlib_handles
= g_hash_table_new_full(g_direct_hash
,
109 g_direct_equal
, NULL
, bt_put
);
110 assert(comp_classes_to_shlib_handles
);
113 __attribute__((destructor
)) static
114 void fini_comp_classes_to_shlib_handles(void) {
115 if (comp_classes_to_shlib_handles
) {
116 g_hash_table_destroy(comp_classes_to_shlib_handles
);
121 void bt_plugin_so_shared_lib_handle_destroy(struct bt_object
*obj
)
123 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
;
126 shared_lib_handle
= container_of(obj
,
127 struct bt_plugin_so_shared_lib_handle
, base
);
129 if (shared_lib_handle
->init_called
&& shared_lib_handle
->exit
) {
130 enum bt_plugin_status status
= shared_lib_handle
->exit();
133 const char *path
= shared_lib_handle
->path
?
134 shared_lib_handle
->path
->str
: "[built-in]";
136 printf_verbose("Plugin in module `%s` exited with error %d\n",
141 if (shared_lib_handle
->module
) {
144 * Valgrind shows incomplete stack traces when
145 * dynamically loaded libraries are closed before it
146 * finishes. Use the BABELTRACE_NO_DLCLOSE in a debug
147 * build to avoid this.
149 const char *var
= getenv("BABELTRACE_NO_DLCLOSE");
151 if (!var
|| strcmp(var
, "1") != 0) {
153 if (!g_module_close(shared_lib_handle
->module
)) {
154 printf_error("Module close error: %s\n",
162 if (shared_lib_handle
->path
) {
163 g_string_free(shared_lib_handle
->path
, TRUE
);
166 g_free(shared_lib_handle
);
170 struct bt_plugin_so_shared_lib_handle
*bt_plugin_so_shared_lib_handle_create(
173 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
175 shared_lib_handle
= g_new0(struct bt_plugin_so_shared_lib_handle
, 1);
176 if (!shared_lib_handle
) {
180 bt_object_init(shared_lib_handle
, bt_plugin_so_shared_lib_handle_destroy
);
186 shared_lib_handle
->path
= g_string_new(path
);
187 if (!shared_lib_handle
->path
) {
191 shared_lib_handle
->module
= g_module_open(path
, 0);
192 if (!shared_lib_handle
->module
) {
193 printf_verbose("Module open error: %s\n", g_module_error());
200 BT_PUT(shared_lib_handle
);
203 return shared_lib_handle
;
207 void bt_plugin_so_destroy_spec_data(struct bt_plugin
*plugin
)
209 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
211 if (!plugin
->spec_data
) {
215 assert(plugin
->type
== BT_PLUGIN_TYPE_SO
);
217 BT_PUT(spec
->shared_lib_handle
);
218 g_free(plugin
->spec_data
);
219 plugin
->spec_data
= NULL
;
223 * This function does the following:
225 * 1. Iterate on the plugin descriptor attributes section and set the
226 * plugin's attributes depending on the attribute types. This
227 * includes the name of the plugin, its description, and its
228 * initialization function, for example.
230 * 2. Iterate on the component class descriptors section and create one
231 * "full descriptor" (temporary structure) for each one that is found
232 * and attached to our plugin descriptor.
234 * 3. Iterate on the component class descriptor attributes section and
235 * set the corresponding full descriptor's attributes depending on
236 * the attribute types. This includes the description of the
237 * component class, as well as its initialization and destroy
240 * 4. Call the user's plugin initialization function, if any is
243 * 5. For each full component class descriptor, create a component class
244 * object, set its optional attributes, and add it to the plugin
247 * 6. Freeze the plugin object.
250 enum bt_plugin_status
bt_plugin_so_init(
251 struct bt_plugin
*plugin
,
252 const struct __bt_plugin_descriptor
*descriptor
,
253 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
254 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
255 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
256 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
257 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
258 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
)
261 * This structure's members point to the plugin's memory
264 struct comp_class_full_descriptor
{
265 const struct __bt_plugin_component_class_descriptor
*descriptor
;
266 const char *description
;
268 bt_component_class_init_method init_method
;
269 bt_component_class_finalize_method finalize_method
;
270 bt_component_class_query_method query_method
;
271 bt_component_class_accept_port_connection_method accept_port_connection_method
;
272 bt_component_class_port_connected_method port_connected_method
;
273 bt_component_class_port_disconnected_method port_disconnected_method
;
274 struct bt_component_class_iterator_methods iterator_methods
;
277 enum bt_plugin_status status
= BT_PLUGIN_STATUS_OK
;
278 struct __bt_plugin_descriptor_attribute
const * const *cur_attr_ptr
;
279 struct __bt_plugin_component_class_descriptor
const * const *cur_cc_descr_ptr
;
280 struct __bt_plugin_component_class_descriptor_attribute
const * const *cur_cc_descr_attr_ptr
;
281 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
282 GArray
*comp_class_full_descriptors
;
286 comp_class_full_descriptors
= g_array_new(FALSE
, TRUE
,
287 sizeof(struct comp_class_full_descriptor
));
288 if (!comp_class_full_descriptors
) {
289 status
= BT_PLUGIN_STATUS_ERROR
;
293 /* Set mandatory attributes */
294 spec
->descriptor
= descriptor
;
295 bt_plugin_set_name(plugin
, descriptor
->name
);
298 * Find and set optional attributes attached to this plugin
301 for (cur_attr_ptr
= attrs_begin
; cur_attr_ptr
!= attrs_end
; cur_attr_ptr
++) {
302 const struct __bt_plugin_descriptor_attribute
*cur_attr
=
305 if (cur_attr
->plugin_descriptor
!= descriptor
) {
309 switch (cur_attr
->type
) {
310 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT
:
311 spec
->init
= cur_attr
->value
.init
;
313 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT
:
314 spec
->shared_lib_handle
->exit
= cur_attr
->value
.exit
;
316 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR
:
317 bt_plugin_set_author(plugin
, cur_attr
->value
.author
);
319 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE
:
320 bt_plugin_set_license(plugin
, cur_attr
->value
.license
);
322 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
323 bt_plugin_set_description(plugin
, cur_attr
->value
.description
);
325 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION
:
326 bt_plugin_set_version(plugin
,
327 (unsigned int) cur_attr
->value
.version
.major
,
328 (unsigned int) cur_attr
->value
.version
.minor
,
329 (unsigned int) cur_attr
->value
.version
.patch
,
330 cur_attr
->value
.version
.extra
);
333 printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for plugin %s\n",
334 cur_attr
->type_name
, cur_attr
->type
,
341 * Find component class descriptors attached to this plugin
342 * descriptor and initialize corresponding full component class
343 * descriptors in the array.
345 for (cur_cc_descr_ptr
= cc_descriptors_begin
; cur_cc_descr_ptr
!= cc_descriptors_end
; cur_cc_descr_ptr
++) {
346 const struct __bt_plugin_component_class_descriptor
*cur_cc_descr
=
348 struct comp_class_full_descriptor full_descriptor
= {0};
350 if (cur_cc_descr
->plugin_descriptor
!= descriptor
) {
354 full_descriptor
.descriptor
= cur_cc_descr
;
355 g_array_append_val(comp_class_full_descriptors
,
360 * Find component class descriptor attributes attached to this
361 * plugin descriptor and update corresponding full component
362 * class descriptors in the array.
364 for (cur_cc_descr_attr_ptr
= cc_descr_attrs_begin
; cur_cc_descr_attr_ptr
!= cc_descr_attrs_end
; cur_cc_descr_attr_ptr
++) {
365 const struct __bt_plugin_component_class_descriptor_attribute
*cur_cc_descr_attr
=
366 *cur_cc_descr_attr_ptr
;
368 if (cur_cc_descr_attr
->comp_class_descriptor
->plugin_descriptor
!=
373 /* Find the corresponding component class descriptor entry */
374 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
375 struct comp_class_full_descriptor
*cc_full_descr
=
376 &g_array_index(comp_class_full_descriptors
,
377 struct comp_class_full_descriptor
, i
);
379 if (cur_cc_descr_attr
->comp_class_descriptor
==
380 cc_full_descr
->descriptor
) {
381 switch (cur_cc_descr_attr
->type
) {
382 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
383 cc_full_descr
->description
=
384 cur_cc_descr_attr
->value
.description
;
386 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP
:
387 cc_full_descr
->help
=
388 cur_cc_descr_attr
->value
.help
;
390 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INIT_METHOD
:
391 cc_full_descr
->init_method
=
392 cur_cc_descr_attr
->value
.init_method
;
394 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD
:
395 cc_full_descr
->finalize_method
=
396 cur_cc_descr_attr
->value
.finalize_method
;
398 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD
:
399 cc_full_descr
->query_method
=
400 cur_cc_descr_attr
->value
.query_method
;
402 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_ACCEPT_PORT_CONNECTION_METHOD
:
403 cc_full_descr
->accept_port_connection_method
=
404 cur_cc_descr_attr
->value
.accept_port_connection_method
;
406 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD
:
407 cc_full_descr
->port_connected_method
=
408 cur_cc_descr_attr
->value
.port_connected_method
;
410 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_DISCONNECTED_METHOD
:
411 cc_full_descr
->port_disconnected_method
=
412 cur_cc_descr_attr
->value
.port_disconnected_method
;
414 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_INIT_METHOD
:
415 cc_full_descr
->iterator_methods
.init
=
416 cur_cc_descr_attr
->value
.notif_iter_init_method
;
418 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_FINALIZE_METHOD
:
419 cc_full_descr
->iterator_methods
.finalize
=
420 cur_cc_descr_attr
->value
.notif_iter_finalize_method
;
422 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_SEEK_TIME_METHOD
:
423 cc_full_descr
->iterator_methods
.seek_time
=
424 cur_cc_descr_attr
->value
.notif_iter_seek_time_method
;
427 printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for component class %s (type %d) in plugin %s\n",
428 cur_cc_descr_attr
->type_name
,
429 cur_cc_descr_attr
->type
,
430 cur_cc_descr_attr
->comp_class_descriptor
->name
,
431 cur_cc_descr_attr
->comp_class_descriptor
->type
,
439 /* Initialize plugin */
441 status
= spec
->init(plugin
);
443 printf_verbose("Plugin `%s` initialization error: %d\n",
444 bt_plugin_get_name(plugin
), status
);
449 spec
->shared_lib_handle
->init_called
= BT_TRUE
;
451 /* Add described component classes to plugin */
452 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
453 struct comp_class_full_descriptor
*cc_full_descr
=
454 &g_array_index(comp_class_full_descriptors
,
455 struct comp_class_full_descriptor
, i
);
456 struct bt_component_class
*comp_class
;
458 switch (cc_full_descr
->descriptor
->type
) {
459 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
460 comp_class
= bt_component_class_source_create(
461 cc_full_descr
->descriptor
->name
,
462 cc_full_descr
->descriptor
->methods
.source
.notif_iter_next
);
464 case BT_COMPONENT_CLASS_TYPE_FILTER
:
465 comp_class
= bt_component_class_filter_create(
466 cc_full_descr
->descriptor
->name
,
467 cc_full_descr
->descriptor
->methods
.source
.notif_iter_next
);
469 case BT_COMPONENT_CLASS_TYPE_SINK
:
470 comp_class
= bt_component_class_sink_create(
471 cc_full_descr
->descriptor
->name
,
472 cc_full_descr
->descriptor
->methods
.sink
.consume
);
475 printf_verbose("WARNING: Unknown component class type %d for component class %s in plugin %s\n",
476 cc_full_descr
->descriptor
->type
,
477 cc_full_descr
->descriptor
->name
,
483 status
= BT_PLUGIN_STATUS_ERROR
;
487 if (cc_full_descr
->description
) {
488 ret
= bt_component_class_set_description(comp_class
,
489 cc_full_descr
->description
);
491 status
= BT_PLUGIN_STATUS_ERROR
;
497 if (cc_full_descr
->help
) {
498 ret
= bt_component_class_set_help(comp_class
,
499 cc_full_descr
->help
);
501 status
= BT_PLUGIN_STATUS_ERROR
;
507 if (cc_full_descr
->init_method
) {
508 ret
= bt_component_class_set_init_method(comp_class
,
509 cc_full_descr
->init_method
);
511 status
= BT_PLUGIN_STATUS_ERROR
;
517 if (cc_full_descr
->finalize_method
) {
518 ret
= bt_component_class_set_finalize_method(comp_class
,
519 cc_full_descr
->finalize_method
);
521 status
= BT_PLUGIN_STATUS_ERROR
;
527 if (cc_full_descr
->query_method
) {
528 ret
= bt_component_class_set_query_method(
529 comp_class
, cc_full_descr
->query_method
);
531 status
= BT_PLUGIN_STATUS_ERROR
;
537 if (cc_full_descr
->accept_port_connection_method
) {
538 ret
= bt_component_class_set_accept_port_connection_method(
539 comp_class
, cc_full_descr
->accept_port_connection_method
);
541 status
= BT_PLUGIN_STATUS_ERROR
;
547 if (cc_full_descr
->port_connected_method
) {
548 ret
= bt_component_class_set_port_connected_method(
549 comp_class
, cc_full_descr
->port_connected_method
);
551 status
= BT_PLUGIN_STATUS_ERROR
;
557 if (cc_full_descr
->port_disconnected_method
) {
558 ret
= bt_component_class_set_port_disconnected_method(
559 comp_class
, cc_full_descr
->port_disconnected_method
);
561 status
= BT_PLUGIN_STATUS_ERROR
;
567 switch (cc_full_descr
->descriptor
->type
) {
568 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
569 if (cc_full_descr
->iterator_methods
.init
) {
570 ret
= bt_component_class_source_set_notification_iterator_init_method(
572 cc_full_descr
->iterator_methods
.init
);
574 status
= BT_PLUGIN_STATUS_ERROR
;
580 if (cc_full_descr
->iterator_methods
.finalize
) {
581 ret
= bt_component_class_source_set_notification_iterator_finalize_method(
583 cc_full_descr
->iterator_methods
.finalize
);
585 status
= BT_PLUGIN_STATUS_ERROR
;
591 if (cc_full_descr
->iterator_methods
.seek_time
) {
592 ret
= bt_component_class_source_set_notification_iterator_seek_time_method(
594 cc_full_descr
->iterator_methods
.seek_time
);
596 status
= BT_PLUGIN_STATUS_ERROR
;
602 case BT_COMPONENT_CLASS_TYPE_FILTER
:
603 if (cc_full_descr
->iterator_methods
.init
) {
604 ret
= bt_component_class_filter_set_notification_iterator_init_method(
606 cc_full_descr
->iterator_methods
.init
);
608 status
= BT_PLUGIN_STATUS_ERROR
;
614 if (cc_full_descr
->iterator_methods
.finalize
) {
615 ret
= bt_component_class_filter_set_notification_iterator_finalize_method(
617 cc_full_descr
->iterator_methods
.finalize
);
619 status
= BT_PLUGIN_STATUS_ERROR
;
625 if (cc_full_descr
->iterator_methods
.seek_time
) {
626 ret
= bt_component_class_filter_set_notification_iterator_seek_time_method(
628 cc_full_descr
->iterator_methods
.seek_time
);
630 status
= BT_PLUGIN_STATUS_ERROR
;
636 case BT_COMPONENT_CLASS_TYPE_SINK
:
643 * Add component class to the plugin object.
645 * This will call back
646 * bt_plugin_so_on_add_component_class() so that we can
647 * add a mapping in comp_classes_to_shlib_handles when
648 * we know the component class is successfully added.
650 status
= bt_plugin_add_component_class(plugin
,
654 printf_verbose("Cannot add component class %s (type %d) to plugin `%s`: status = %d\n",
655 cc_full_descr
->descriptor
->name
,
656 cc_full_descr
->descriptor
->type
,
657 bt_plugin_get_name(plugin
), status
);
663 * All the plugin's component classes should be added at this
664 * point. We freeze the plugin so that it's not possible to add
665 * component classes to this plugin object after this stage
666 * (plugin object becomes immutable).
668 bt_plugin_freeze(plugin
);
671 g_array_free(comp_class_full_descriptors
, TRUE
);
676 struct bt_plugin
*bt_plugin_so_create_empty(
677 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
)
679 struct bt_plugin
*plugin
;
680 struct bt_plugin_so_spec_data
*spec
;
682 plugin
= bt_plugin_create_empty(BT_PLUGIN_TYPE_SO
);
687 plugin
->destroy_spec_data
= bt_plugin_so_destroy_spec_data
;
688 plugin
->spec_data
= g_new0(struct bt_plugin_so_spec_data
, 1);
689 if (!plugin
->spec_data
) {
693 spec
= plugin
->spec_data
;
694 spec
->shared_lib_handle
= bt_get(shared_lib_handle
);
705 struct bt_plugin_set
*bt_plugin_so_create_all_from_sections(
706 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
,
707 struct __bt_plugin_descriptor
const * const *descriptors_begin
,
708 struct __bt_plugin_descriptor
const * const *descriptors_end
,
709 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
710 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
711 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
712 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
713 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
714 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
)
716 size_t descriptor_count
;
718 size_t cc_descriptors_count
;
719 size_t cc_descr_attrs_count
;
721 struct bt_plugin_set
*plugin_set
= NULL
;
723 descriptor_count
= descriptors_end
- descriptors_begin
;
724 attrs_count
= attrs_end
- attrs_begin
;
725 cc_descriptors_count
= cc_descriptors_end
- cc_descriptors_begin
;
726 cc_descr_attrs_count
= cc_descr_attrs_end
- cc_descr_attrs_begin
;
727 printf_verbose("Section: Plugin descriptors: [%p - %p], (%zu elements)\n",
728 descriptors_begin
, descriptors_end
, descriptor_count
);
729 printf_verbose("Section: Plugin descriptor attributes: [%p - %p], (%zu elements)\n",
730 attrs_begin
, attrs_end
, attrs_count
);
731 printf_verbose("Section: Plugin component class descriptors: [%p - %p], (%zu elements)\n",
732 cc_descriptors_begin
, cc_descriptors_end
, cc_descriptors_count
);
733 printf_verbose("Section: Plugin component class descriptor attributes: [%p - %p], (%zu elements)\n",
734 cc_descr_attrs_begin
, cc_descr_attrs_end
, cc_descr_attrs_count
);
735 plugin_set
= bt_plugin_set_create();
740 for (i
= 0; i
< descriptor_count
; i
++) {
741 enum bt_plugin_status status
;
742 const struct __bt_plugin_descriptor
*descriptor
=
743 descriptors_begin
[i
];
744 struct bt_plugin
*plugin
;
746 printf_verbose("Loading plugin %s (ABI %d.%d)\n", descriptor
->name
,
747 descriptor
->major
, descriptor
->minor
);
749 if (descriptor
->major
> __BT_PLUGIN_VERSION_MAJOR
) {
750 printf_error("Unknown plugin's major version: %d\n",
755 plugin
= bt_plugin_so_create_empty(shared_lib_handle
);
757 printf_error("Cannot allocate plugin object for plugin %s\n",
762 if (shared_lib_handle
&& shared_lib_handle
->path
) {
763 bt_plugin_set_path(plugin
, shared_lib_handle
->path
->str
);
766 status
= bt_plugin_so_init(plugin
, descriptor
, attrs_begin
,
767 attrs_end
, cc_descriptors_begin
, cc_descriptors_end
,
768 cc_descr_attrs_begin
, cc_descr_attrs_end
);
770 printf_error("Cannot initialize plugin object %s\n",
776 /* Add to plugin set */
777 bt_plugin_set_add_plugin(plugin_set
, plugin
);
791 struct bt_plugin_set
*bt_plugin_so_create_all_from_static(void)
793 struct bt_plugin_set
*plugin_set
= NULL
;
794 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
=
795 bt_plugin_so_shared_lib_handle_create(NULL
);
797 if (!shared_lib_handle
) {
801 plugin_set
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
802 SECTION_BEGIN(__bt_plugin_descriptors
),
803 SECTION_END(__bt_plugin_descriptors
),
804 SECTION_BEGIN(__bt_plugin_descriptor_attributes
),
805 SECTION_END(__bt_plugin_descriptor_attributes
),
806 SECTION_BEGIN(__bt_plugin_component_class_descriptors
),
807 SECTION_END(__bt_plugin_component_class_descriptors
),
808 SECTION_BEGIN(__bt_plugin_component_class_descriptor_attributes
),
809 SECTION_END(__bt_plugin_component_class_descriptor_attributes
));
812 BT_PUT(shared_lib_handle
);
818 struct bt_plugin_set
*bt_plugin_so_create_all_from_file(const char *path
)
821 struct bt_plugin_set
*plugin_set
= NULL
;
822 struct __bt_plugin_descriptor
const * const *descriptors_begin
= NULL
;
823 struct __bt_plugin_descriptor
const * const *descriptors_end
= NULL
;
824 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
= NULL
;
825 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
= NULL
;
826 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
= NULL
;
827 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
= NULL
;
828 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
= NULL
;
829 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
= NULL
;
830 bt_bool is_libtool_wrapper
= BT_FALSE
, is_shared_object
= BT_FALSE
;
831 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
837 path_len
= strlen(path
);
838 if (path_len
<= PLUGIN_SUFFIX_LEN
) {
844 * Check if the file ends with a known plugin file type suffix (i.e. .so
847 is_libtool_wrapper
= !strncmp(LIBTOOL_PLUGIN_SUFFIX
,
848 path
+ path_len
- LIBTOOL_PLUGIN_SUFFIX_LEN
,
849 LIBTOOL_PLUGIN_SUFFIX_LEN
);
850 is_shared_object
= !strncmp(NATIVE_PLUGIN_SUFFIX
,
851 path
+ path_len
- NATIVE_PLUGIN_SUFFIX_LEN
,
852 NATIVE_PLUGIN_SUFFIX_LEN
);
853 if (!is_shared_object
&& !is_libtool_wrapper
) {
854 /* Name indicates that this is not a plugin file. */
858 shared_lib_handle
= bt_plugin_so_shared_lib_handle_create(path
);
859 if (!shared_lib_handle
) {
863 if (!g_module_symbol(shared_lib_handle
->module
, "__start___bt_plugin_descriptors",
864 (gpointer
*) &descriptors_begin
)) {
865 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
866 "__start___bt_plugin_descriptors",
867 g_module_name(shared_lib_handle
->module
));
871 if (!g_module_symbol(shared_lib_handle
->module
, "__stop___bt_plugin_descriptors",
872 (gpointer
*) &descriptors_end
)) {
873 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
874 "__stop___bt_plugin_descriptors",
875 g_module_name(shared_lib_handle
->module
));
879 if (!g_module_symbol(shared_lib_handle
->module
, "__start___bt_plugin_descriptor_attributes",
880 (gpointer
*) &attrs_begin
)) {
881 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
882 "__start___bt_plugin_descriptor_attributes",
883 g_module_name(shared_lib_handle
->module
));
886 if (!g_module_symbol(shared_lib_handle
->module
, "__stop___bt_plugin_descriptor_attributes",
887 (gpointer
*) &attrs_end
)) {
888 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
889 "__stop___bt_plugin_descriptor_attributes",
890 g_module_name(shared_lib_handle
->module
));
893 if ((!!attrs_begin
- !!attrs_end
) != 0) {
894 printf_verbose("Found __start___bt_plugin_descriptor_attributes or __stop___bt_plugin_descriptor_attributes symbol, but not both in %s\n",
895 g_module_name(shared_lib_handle
->module
));
899 if (!g_module_symbol(shared_lib_handle
->module
, "__start___bt_plugin_component_class_descriptors",
900 (gpointer
*) &cc_descriptors_begin
)) {
901 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
902 "__start___bt_plugin_component_class_descriptors",
903 g_module_name(shared_lib_handle
->module
));
906 if (!g_module_symbol(shared_lib_handle
->module
, "__stop___bt_plugin_component_class_descriptors",
907 (gpointer
*) &cc_descriptors_end
)) {
908 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
909 "__stop___bt_plugin_component_class_descriptors",
910 g_module_name(shared_lib_handle
->module
));
913 if ((!!cc_descriptors_begin
- !!cc_descriptors_end
) != 0) {
914 printf_verbose("Found __start___bt_plugin_component_class_descriptors or __stop___bt_plugin_component_class_descriptors symbol, but not both in %s\n",
915 g_module_name(shared_lib_handle
->module
));
919 if (!g_module_symbol(shared_lib_handle
->module
, "__start___bt_plugin_component_class_descriptor_attributes",
920 (gpointer
*) &cc_descr_attrs_begin
)) {
921 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
922 "__start___bt_plugin_component_class_descriptor_attributes",
923 g_module_name(shared_lib_handle
->module
));
926 if (!g_module_symbol(shared_lib_handle
->module
, "__stop___bt_plugin_component_class_descriptor_attributes",
927 (gpointer
*) &cc_descr_attrs_end
)) {
928 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
929 "__stop___bt_plugin_component_class_descriptor_attributes",
930 g_module_name(shared_lib_handle
->module
));
933 if ((!!cc_descr_attrs_begin
- !!cc_descr_attrs_end
) != 0) {
934 printf_verbose("Found __start___bt_plugin_component_class_descriptor_attributes or __stop___bt_plugin_component_class_descriptor_attributes symbol, but not both in %s\n",
935 g_module_name(shared_lib_handle
->module
));
939 /* Initialize plugin */
940 plugin_set
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
941 descriptors_begin
, descriptors_end
, attrs_begin
, attrs_end
,
942 cc_descriptors_begin
, cc_descriptors_end
,
943 cc_descr_attrs_begin
, cc_descr_attrs_end
);
946 BT_PUT(shared_lib_handle
);
951 void plugin_comp_class_destroy_listener(struct bt_component_class
*comp_class
,
954 gboolean exists
= g_hash_table_remove(comp_classes_to_shlib_handles
,
960 void bt_plugin_so_on_add_component_class(struct bt_plugin
*plugin
,
961 struct bt_component_class
*comp_class
)
963 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
965 assert(plugin
->spec_data
);
966 assert(plugin
->type
== BT_PLUGIN_TYPE_SO
);
968 /* Map component class pointer to shared lib handle in global HT */
969 g_hash_table_insert(comp_classes_to_shlib_handles
, comp_class
,
970 bt_get(spec
->shared_lib_handle
));
972 /* Add our custom destroy listener */
973 bt_component_class_add_destroy_listener(comp_class
,
974 plugin_comp_class_destroy_listener
, NULL
);