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>
42 #define NATIVE_PLUGIN_SUFFIX ".so"
43 #define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
44 #define LIBTOOL_PLUGIN_SUFFIX ".la"
45 #define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
47 #define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
48 sizeof(LIBTOOL_PLUGIN_SUFFIX))
50 #define SECTION_BEGIN(_name) (&(__start_##_name))
51 #define SECTION_END(_name) (&(__stop_##_name))
52 #define SECTION_ELEMENT_COUNT(_name) (SECTION_END(_name) - SECTION_BEGIN(_name))
54 #define DECLARE_SECTION(_type, _name) \
55 extern _type __start_##_name __attribute((weak)); \
56 extern _type __stop_##_name __attribute((weak))
58 DECLARE_SECTION(struct __bt_plugin_descriptor
const *, __bt_plugin_descriptors
);
59 DECLARE_SECTION(struct __bt_plugin_descriptor_attribute
const *, __bt_plugin_descriptor_attributes
);
60 DECLARE_SECTION(struct __bt_plugin_component_class_descriptor
const *, __bt_plugin_component_class_descriptors
);
61 DECLARE_SECTION(struct __bt_plugin_component_class_descriptor_attribute
const *, __bt_plugin_component_class_descriptor_attributes
);
64 * This hash table, global to the library, maps component class pointers
65 * to shared library handles.
67 * The keys (component classes) are NOT owned by this hash table, whereas
68 * the values (shared library handles) are owned by this hash table.
70 * The keys are the component classes created with
71 * bt_plugin_add_component_class(). They keep the shared library handle
72 * object created by their plugin alive so that the plugin's code is
73 * not discarded when it could still be in use by living components
74 * created from those component classes:
76 * [component] --ref-> [component class] --through this HT-> [shlib handle]
78 * This hash table exists for two reasons:
80 * 1. To allow this application:
82 * my_plugins = bt_plugin_create_all_from_file("/path/to/my-plugin.so");
83 * // instantiate components from a plugin's component classes
84 * // put plugins and free my_plugins here
85 * // user code of instantiated components still exists
87 * 2. To decouple the plugin subsystem from the component subsystem:
88 * while plugins objects need to know component class objects, the
89 * opposite is not necessary, thus it makes no sense for a component
90 * class to keep a reference to the plugin object from which it was
93 * An entry is removed from this HT when a component class is destroyed
94 * thanks to a custom destroy listener. When the entry is removed, the
95 * GLib function calls the value destroy notifier of the HT, which is
96 * bt_put(). This decreases the reference count of the mapped shared
97 * library handle. Assuming the original plugin object which contained
98 * some component classes is put first, when the last component class is
99 * removed from this HT, the shared library handle object's reference
100 * count falls to zero and the shared library is finally closed.
103 GHashTable
*comp_classes_to_shlib_handles
;
105 __attribute__((constructor
)) static
106 void init_comp_classes_to_shlib_handles(void) {
107 comp_classes_to_shlib_handles
= g_hash_table_new_full(g_direct_hash
,
108 g_direct_equal
, NULL
, bt_put
);
109 assert(comp_classes_to_shlib_handles
);
112 __attribute__((destructor
)) static
113 void fini_comp_classes_to_shlib_handles(void) {
114 if (comp_classes_to_shlib_handles
) {
115 g_hash_table_destroy(comp_classes_to_shlib_handles
);
120 void bt_plugin_so_shared_lib_handle_destroy(struct bt_object
*obj
)
122 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
;
125 shared_lib_handle
= container_of(obj
,
126 struct bt_plugin_so_shared_lib_handle
, base
);
128 if (shared_lib_handle
->init_called
&& shared_lib_handle
->exit
) {
129 enum bt_plugin_status status
= shared_lib_handle
->exit();
132 const char *path
= shared_lib_handle
->path
?
133 shared_lib_handle
->path
->str
: "[built-in]";
135 printf_verbose("Plugin in module `%s` exited with error %d\n",
140 if (shared_lib_handle
->module
) {
141 if (!g_module_close(shared_lib_handle
->module
)) {
142 printf_error("Module close error: %s\n",
147 if (shared_lib_handle
->path
) {
148 g_string_free(shared_lib_handle
->path
, TRUE
);
151 g_free(shared_lib_handle
);
155 struct bt_plugin_so_shared_lib_handle
*bt_plugin_so_shared_lib_handle_create(
158 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
160 shared_lib_handle
= g_new0(struct bt_plugin_so_shared_lib_handle
, 1);
161 if (!shared_lib_handle
) {
165 bt_object_init(shared_lib_handle
, bt_plugin_so_shared_lib_handle_destroy
);
171 shared_lib_handle
->path
= g_string_new(path
);
172 if (!shared_lib_handle
->path
) {
176 shared_lib_handle
->module
= g_module_open(path
, 0);
177 if (!shared_lib_handle
->module
) {
178 printf_verbose("Module open error: %s\n", g_module_error());
185 BT_PUT(shared_lib_handle
);
188 return shared_lib_handle
;
192 void bt_plugin_so_destroy_spec_data(struct bt_plugin
*plugin
)
194 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
196 if (!plugin
->spec_data
) {
200 assert(plugin
->type
== BT_PLUGIN_TYPE_SO
);
202 BT_PUT(spec
->shared_lib_handle
);
203 g_free(plugin
->spec_data
);
204 plugin
->spec_data
= NULL
;
208 * This function does the following:
210 * 1. Iterate on the plugin descriptor attributes section and set the
211 * plugin's attributes depending on the attribute types. This
212 * includes the name of the plugin, its description, and its
213 * initialization function, for example.
215 * 2. Iterate on the component class descriptors section and create one
216 * "full descriptor" (temporary structure) for each one that is found
217 * and attached to our plugin descriptor.
219 * 3. Iterate on the component class descriptor attributes section and
220 * set the corresponding full descriptor's attributes depending on
221 * the attribute types. This includes the description of the
222 * component class, as well as its initialization and destroy
225 * 4. Call the user's plugin initialization function, if any is
228 * 5. For each full component class descriptor, create a component class
229 * object, set its optional attributes, and add it to the plugin
232 * 6. Freeze the plugin object.
235 enum bt_plugin_status
bt_plugin_so_init(
236 struct bt_plugin
*plugin
,
237 const struct __bt_plugin_descriptor
*descriptor
,
238 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
239 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
240 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
241 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
242 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
243 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
)
246 * This structure's members point to the plugin's memory
249 struct comp_class_full_descriptor
{
250 const struct __bt_plugin_component_class_descriptor
*descriptor
;
251 const char *description
;
253 bt_component_class_init_method init_method
;
254 bt_component_class_finalize_method finalize_method
;
255 bt_component_class_query_method query_method
;
256 bt_component_class_accept_port_connection_method accept_port_connection_method
;
257 bt_component_class_port_connected_method port_connected_method
;
258 bt_component_class_port_disconnected_method port_disconnected_method
;
259 struct bt_component_class_iterator_methods iterator_methods
;
262 enum bt_plugin_status status
= BT_PLUGIN_STATUS_OK
;
263 struct __bt_plugin_descriptor_attribute
const * const *cur_attr_ptr
;
264 struct __bt_plugin_component_class_descriptor
const * const *cur_cc_descr_ptr
;
265 struct __bt_plugin_component_class_descriptor_attribute
const * const *cur_cc_descr_attr_ptr
;
266 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
267 GArray
*comp_class_full_descriptors
;
271 comp_class_full_descriptors
= g_array_new(FALSE
, TRUE
,
272 sizeof(struct comp_class_full_descriptor
));
273 if (!comp_class_full_descriptors
) {
274 status
= BT_PLUGIN_STATUS_ERROR
;
278 /* Set mandatory attributes */
279 spec
->descriptor
= descriptor
;
280 bt_plugin_set_name(plugin
, descriptor
->name
);
283 * Find and set optional attributes attached to this plugin
286 for (cur_attr_ptr
= attrs_begin
; cur_attr_ptr
!= attrs_end
; cur_attr_ptr
++) {
287 const struct __bt_plugin_descriptor_attribute
*cur_attr
=
290 if (cur_attr
->plugin_descriptor
!= descriptor
) {
294 switch (cur_attr
->type
) {
295 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT
:
296 spec
->init
= cur_attr
->value
.init
;
298 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT
:
299 spec
->shared_lib_handle
->exit
= cur_attr
->value
.exit
;
301 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR
:
302 bt_plugin_set_author(plugin
, cur_attr
->value
.author
);
304 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE
:
305 bt_plugin_set_license(plugin
, cur_attr
->value
.license
);
307 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
308 bt_plugin_set_description(plugin
, cur_attr
->value
.description
);
310 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION
:
311 bt_plugin_set_version(plugin
,
312 (unsigned int) cur_attr
->value
.version
.major
,
313 (unsigned int) cur_attr
->value
.version
.minor
,
314 (unsigned int) cur_attr
->value
.version
.patch
,
315 cur_attr
->value
.version
.extra
);
318 printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for plugin %s\n",
319 cur_attr
->type_name
, cur_attr
->type
,
326 * Find component class descriptors attached to this plugin
327 * descriptor and initialize corresponding full component class
328 * descriptors in the array.
330 for (cur_cc_descr_ptr
= cc_descriptors_begin
; cur_cc_descr_ptr
!= cc_descriptors_end
; cur_cc_descr_ptr
++) {
331 const struct __bt_plugin_component_class_descriptor
*cur_cc_descr
=
333 struct comp_class_full_descriptor full_descriptor
= {0};
335 if (cur_cc_descr
->plugin_descriptor
!= descriptor
) {
339 full_descriptor
.descriptor
= cur_cc_descr
;
340 g_array_append_val(comp_class_full_descriptors
,
345 * Find component class descriptor attributes attached to this
346 * plugin descriptor and update corresponding full component
347 * class descriptors in the array.
349 for (cur_cc_descr_attr_ptr
= cc_descr_attrs_begin
; cur_cc_descr_attr_ptr
!= cc_descr_attrs_end
; cur_cc_descr_attr_ptr
++) {
350 const struct __bt_plugin_component_class_descriptor_attribute
*cur_cc_descr_attr
=
351 *cur_cc_descr_attr_ptr
;
353 if (cur_cc_descr_attr
->comp_class_descriptor
->plugin_descriptor
!=
358 /* Find the corresponding component class descriptor entry */
359 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
360 struct comp_class_full_descriptor
*cc_full_descr
=
361 &g_array_index(comp_class_full_descriptors
,
362 struct comp_class_full_descriptor
, i
);
364 if (cur_cc_descr_attr
->comp_class_descriptor
==
365 cc_full_descr
->descriptor
) {
366 switch (cur_cc_descr_attr
->type
) {
367 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION
:
368 cc_full_descr
->description
=
369 cur_cc_descr_attr
->value
.description
;
371 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP
:
372 cc_full_descr
->help
=
373 cur_cc_descr_attr
->value
.help
;
375 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INIT_METHOD
:
376 cc_full_descr
->init_method
=
377 cur_cc_descr_attr
->value
.init_method
;
379 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD
:
380 cc_full_descr
->finalize_method
=
381 cur_cc_descr_attr
->value
.finalize_method
;
383 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD
:
384 cc_full_descr
->query_method
=
385 cur_cc_descr_attr
->value
.query_method
;
387 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_ACCEPT_PORT_CONNECTION_METHOD
:
388 cc_full_descr
->accept_port_connection_method
=
389 cur_cc_descr_attr
->value
.accept_port_connection_method
;
391 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD
:
392 cc_full_descr
->port_connected_method
=
393 cur_cc_descr_attr
->value
.port_connected_method
;
395 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_DISCONNECTED_METHOD
:
396 cc_full_descr
->port_disconnected_method
=
397 cur_cc_descr_attr
->value
.port_disconnected_method
;
399 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_INIT_METHOD
:
400 cc_full_descr
->iterator_methods
.init
=
401 cur_cc_descr_attr
->value
.notif_iter_init_method
;
403 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_FINALIZE_METHOD
:
404 cc_full_descr
->iterator_methods
.finalize
=
405 cur_cc_descr_attr
->value
.notif_iter_finalize_method
;
407 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_SEEK_TIME_METHOD
:
408 cc_full_descr
->iterator_methods
.seek_time
=
409 cur_cc_descr_attr
->value
.notif_iter_seek_time_method
;
412 printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for component class %s (type %d) in plugin %s\n",
413 cur_cc_descr_attr
->type_name
,
414 cur_cc_descr_attr
->type
,
415 cur_cc_descr_attr
->comp_class_descriptor
->name
,
416 cur_cc_descr_attr
->comp_class_descriptor
->type
,
424 /* Initialize plugin */
426 status
= spec
->init(plugin
);
428 printf_verbose("Plugin `%s` initialization error: %d\n",
429 bt_plugin_get_name(plugin
), status
);
434 spec
->shared_lib_handle
->init_called
= BT_TRUE
;
436 /* Add described component classes to plugin */
437 for (i
= 0; i
< comp_class_full_descriptors
->len
; i
++) {
438 struct comp_class_full_descriptor
*cc_full_descr
=
439 &g_array_index(comp_class_full_descriptors
,
440 struct comp_class_full_descriptor
, i
);
441 struct bt_component_class
*comp_class
;
443 switch (cc_full_descr
->descriptor
->type
) {
444 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
445 comp_class
= bt_component_class_source_create(
446 cc_full_descr
->descriptor
->name
,
447 cc_full_descr
->descriptor
->methods
.source
.notif_iter_next
);
449 case BT_COMPONENT_CLASS_TYPE_FILTER
:
450 comp_class
= bt_component_class_filter_create(
451 cc_full_descr
->descriptor
->name
,
452 cc_full_descr
->descriptor
->methods
.source
.notif_iter_next
);
454 case BT_COMPONENT_CLASS_TYPE_SINK
:
455 comp_class
= bt_component_class_sink_create(
456 cc_full_descr
->descriptor
->name
,
457 cc_full_descr
->descriptor
->methods
.sink
.consume
);
460 printf_verbose("WARNING: Unknown component class type %d for component class %s in plugin %s\n",
461 cc_full_descr
->descriptor
->type
,
462 cc_full_descr
->descriptor
->name
,
468 status
= BT_PLUGIN_STATUS_ERROR
;
472 if (cc_full_descr
->description
) {
473 ret
= bt_component_class_set_description(comp_class
,
474 cc_full_descr
->description
);
476 status
= BT_PLUGIN_STATUS_ERROR
;
482 if (cc_full_descr
->help
) {
483 ret
= bt_component_class_set_help(comp_class
,
484 cc_full_descr
->help
);
486 status
= BT_PLUGIN_STATUS_ERROR
;
492 if (cc_full_descr
->init_method
) {
493 ret
= bt_component_class_set_init_method(comp_class
,
494 cc_full_descr
->init_method
);
496 status
= BT_PLUGIN_STATUS_ERROR
;
502 if (cc_full_descr
->finalize_method
) {
503 ret
= bt_component_class_set_finalize_method(comp_class
,
504 cc_full_descr
->finalize_method
);
506 status
= BT_PLUGIN_STATUS_ERROR
;
512 if (cc_full_descr
->query_method
) {
513 ret
= bt_component_class_set_query_method(
514 comp_class
, cc_full_descr
->query_method
);
516 status
= BT_PLUGIN_STATUS_ERROR
;
522 if (cc_full_descr
->accept_port_connection_method
) {
523 ret
= bt_component_class_set_accept_port_connection_method(
524 comp_class
, cc_full_descr
->accept_port_connection_method
);
526 status
= BT_PLUGIN_STATUS_ERROR
;
532 if (cc_full_descr
->port_connected_method
) {
533 ret
= bt_component_class_set_port_connected_method(
534 comp_class
, cc_full_descr
->port_connected_method
);
536 status
= BT_PLUGIN_STATUS_ERROR
;
542 if (cc_full_descr
->port_disconnected_method
) {
543 ret
= bt_component_class_set_port_disconnected_method(
544 comp_class
, cc_full_descr
->port_disconnected_method
);
546 status
= BT_PLUGIN_STATUS_ERROR
;
552 switch (cc_full_descr
->descriptor
->type
) {
553 case BT_COMPONENT_CLASS_TYPE_SOURCE
:
554 if (cc_full_descr
->iterator_methods
.init
) {
555 ret
= bt_component_class_source_set_notification_iterator_init_method(
557 cc_full_descr
->iterator_methods
.init
);
559 status
= BT_PLUGIN_STATUS_ERROR
;
565 if (cc_full_descr
->iterator_methods
.finalize
) {
566 ret
= bt_component_class_source_set_notification_iterator_finalize_method(
568 cc_full_descr
->iterator_methods
.finalize
);
570 status
= BT_PLUGIN_STATUS_ERROR
;
576 if (cc_full_descr
->iterator_methods
.seek_time
) {
577 ret
= bt_component_class_source_set_notification_iterator_seek_time_method(
579 cc_full_descr
->iterator_methods
.seek_time
);
581 status
= BT_PLUGIN_STATUS_ERROR
;
587 case BT_COMPONENT_CLASS_TYPE_FILTER
:
588 if (cc_full_descr
->iterator_methods
.init
) {
589 ret
= bt_component_class_filter_set_notification_iterator_init_method(
591 cc_full_descr
->iterator_methods
.init
);
593 status
= BT_PLUGIN_STATUS_ERROR
;
599 if (cc_full_descr
->iterator_methods
.finalize
) {
600 ret
= bt_component_class_filter_set_notification_iterator_finalize_method(
602 cc_full_descr
->iterator_methods
.finalize
);
604 status
= BT_PLUGIN_STATUS_ERROR
;
610 if (cc_full_descr
->iterator_methods
.seek_time
) {
611 ret
= bt_component_class_filter_set_notification_iterator_seek_time_method(
613 cc_full_descr
->iterator_methods
.seek_time
);
615 status
= BT_PLUGIN_STATUS_ERROR
;
621 case BT_COMPONENT_CLASS_TYPE_SINK
:
629 * Add component class to the plugin object.
631 * This will call back
632 * bt_plugin_so_on_add_component_class() so that we can
633 * add a mapping in comp_classes_to_shlib_handles when
634 * we know the component class is successfully added.
636 status
= bt_plugin_add_component_class(plugin
,
640 printf_verbose("Cannot add component class %s (type %d) to plugin `%s`: status = %d\n",
641 cc_full_descr
->descriptor
->name
,
642 cc_full_descr
->descriptor
->type
,
643 bt_plugin_get_name(plugin
), status
);
649 * All the plugin's component classes should be added at this
650 * point. We freeze the plugin so that it's not possible to add
651 * component classes to this plugin object after this stage
652 * (plugin object becomes immutable).
654 bt_plugin_freeze(plugin
);
657 g_array_free(comp_class_full_descriptors
, TRUE
);
662 struct bt_plugin
*bt_plugin_so_create_empty(
663 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
)
665 struct bt_plugin
*plugin
;
666 struct bt_plugin_so_spec_data
*spec
;
668 plugin
= bt_plugin_create_empty(BT_PLUGIN_TYPE_SO
);
673 plugin
->destroy_spec_data
= bt_plugin_so_destroy_spec_data
;
674 plugin
->spec_data
= g_new0(struct bt_plugin_so_spec_data
, 1);
675 if (!plugin
->spec_data
) {
679 spec
= plugin
->spec_data
;
680 spec
->shared_lib_handle
= bt_get(shared_lib_handle
);
691 struct bt_plugin_set
*bt_plugin_so_create_all_from_sections(
692 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
,
693 struct __bt_plugin_descriptor
const * const *descriptors_begin
,
694 struct __bt_plugin_descriptor
const * const *descriptors_end
,
695 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
,
696 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
,
697 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
,
698 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
,
699 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
,
700 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
)
702 size_t descriptor_count
;
704 size_t cc_descriptors_count
;
705 size_t cc_descr_attrs_count
;
707 struct bt_plugin_set
*plugin_set
= NULL
;
709 descriptor_count
= descriptors_end
- descriptors_begin
;
710 attrs_count
= attrs_end
- attrs_begin
;
711 cc_descriptors_count
= cc_descriptors_end
- cc_descriptors_begin
;
712 cc_descr_attrs_count
= cc_descr_attrs_end
- cc_descr_attrs_begin
;
713 printf_verbose("Section: Plugin descriptors: [%p - %p], (%zu elements)\n",
714 descriptors_begin
, descriptors_end
, descriptor_count
);
715 printf_verbose("Section: Plugin descriptor attributes: [%p - %p], (%zu elements)\n",
716 attrs_begin
, attrs_end
, attrs_count
);
717 printf_verbose("Section: Plugin component class descriptors: [%p - %p], (%zu elements)\n",
718 cc_descriptors_begin
, cc_descriptors_end
, cc_descriptors_count
);
719 printf_verbose("Section: Plugin component class descriptor attributes: [%p - %p], (%zu elements)\n",
720 cc_descr_attrs_begin
, cc_descr_attrs_end
, cc_descr_attrs_count
);
721 plugin_set
= bt_plugin_set_create();
726 for (i
= 0; i
< descriptor_count
; i
++) {
727 enum bt_plugin_status status
;
728 const struct __bt_plugin_descriptor
*descriptor
=
729 descriptors_begin
[i
];
730 struct bt_plugin
*plugin
;
732 printf_verbose("Loading plugin %s (ABI %d.%d)\n", descriptor
->name
,
733 descriptor
->major
, descriptor
->minor
);
735 if (descriptor
->major
> __BT_PLUGIN_VERSION_MAJOR
) {
736 printf_error("Unknown plugin's major version: %d\n",
741 plugin
= bt_plugin_so_create_empty(shared_lib_handle
);
743 printf_error("Cannot allocate plugin object for plugin %s\n",
748 if (shared_lib_handle
&& shared_lib_handle
->path
) {
749 bt_plugin_set_path(plugin
, shared_lib_handle
->path
->str
);
752 status
= bt_plugin_so_init(plugin
, descriptor
, attrs_begin
,
753 attrs_end
, cc_descriptors_begin
, cc_descriptors_end
,
754 cc_descr_attrs_begin
, cc_descr_attrs_end
);
756 printf_error("Cannot initialize plugin object %s\n",
762 /* Add to plugin set */
763 bt_plugin_set_add_plugin(plugin_set
, plugin
);
777 struct bt_plugin_set
*bt_plugin_so_create_all_from_static(void)
779 struct bt_plugin_set
*plugin_set
= NULL
;
780 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
=
781 bt_plugin_so_shared_lib_handle_create(NULL
);
783 if (!shared_lib_handle
) {
787 plugin_set
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
788 SECTION_BEGIN(__bt_plugin_descriptors
),
789 SECTION_END(__bt_plugin_descriptors
),
790 SECTION_BEGIN(__bt_plugin_descriptor_attributes
),
791 SECTION_END(__bt_plugin_descriptor_attributes
),
792 SECTION_BEGIN(__bt_plugin_component_class_descriptors
),
793 SECTION_END(__bt_plugin_component_class_descriptors
),
794 SECTION_BEGIN(__bt_plugin_component_class_descriptor_attributes
),
795 SECTION_END(__bt_plugin_component_class_descriptor_attributes
));
798 BT_PUT(shared_lib_handle
);
804 struct bt_plugin_set
*bt_plugin_so_create_all_from_file(const char *path
)
807 struct bt_plugin_set
*plugin_set
= NULL
;
808 struct __bt_plugin_descriptor
const * const *descriptors_begin
= NULL
;
809 struct __bt_plugin_descriptor
const * const *descriptors_end
= NULL
;
810 struct __bt_plugin_descriptor_attribute
const * const *attrs_begin
= NULL
;
811 struct __bt_plugin_descriptor_attribute
const * const *attrs_end
= NULL
;
812 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_begin
= NULL
;
813 struct __bt_plugin_component_class_descriptor
const * const *cc_descriptors_end
= NULL
;
814 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_begin
= NULL
;
815 struct __bt_plugin_component_class_descriptor_attribute
const * const *cc_descr_attrs_end
= NULL
;
816 bt_bool is_libtool_wrapper
= BT_FALSE
, is_shared_object
= BT_FALSE
;
817 struct bt_plugin_so_shared_lib_handle
*shared_lib_handle
= NULL
;
823 path_len
= strlen(path
);
824 if (path_len
<= PLUGIN_SUFFIX_LEN
) {
830 * Check if the file ends with a known plugin file type suffix (i.e. .so
833 is_libtool_wrapper
= !strncmp(LIBTOOL_PLUGIN_SUFFIX
,
834 path
+ path_len
- LIBTOOL_PLUGIN_SUFFIX_LEN
,
835 LIBTOOL_PLUGIN_SUFFIX_LEN
);
836 is_shared_object
= !strncmp(NATIVE_PLUGIN_SUFFIX
,
837 path
+ path_len
- NATIVE_PLUGIN_SUFFIX_LEN
,
838 NATIVE_PLUGIN_SUFFIX_LEN
);
839 if (!is_shared_object
&& !is_libtool_wrapper
) {
840 /* Name indicates that this is not a plugin file. */
844 shared_lib_handle
= bt_plugin_so_shared_lib_handle_create(path
);
845 if (!shared_lib_handle
) {
849 if (!g_module_symbol(shared_lib_handle
->module
, "__start___bt_plugin_descriptors",
850 (gpointer
*) &descriptors_begin
)) {
851 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
852 "__start___bt_plugin_descriptors",
853 g_module_name(shared_lib_handle
->module
));
857 if (!g_module_symbol(shared_lib_handle
->module
, "__stop___bt_plugin_descriptors",
858 (gpointer
*) &descriptors_end
)) {
859 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
860 "__stop___bt_plugin_descriptors",
861 g_module_name(shared_lib_handle
->module
));
865 if (!g_module_symbol(shared_lib_handle
->module
, "__start___bt_plugin_descriptor_attributes",
866 (gpointer
*) &attrs_begin
)) {
867 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
868 "__start___bt_plugin_descriptor_attributes",
869 g_module_name(shared_lib_handle
->module
));
872 if (!g_module_symbol(shared_lib_handle
->module
, "__stop___bt_plugin_descriptor_attributes",
873 (gpointer
*) &attrs_end
)) {
874 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
875 "__stop___bt_plugin_descriptor_attributes",
876 g_module_name(shared_lib_handle
->module
));
879 if ((!!attrs_begin
- !!attrs_end
) != 0) {
880 printf_verbose("Found __start___bt_plugin_descriptor_attributes or __stop___bt_plugin_descriptor_attributes symbol, but not both in %s\n",
881 g_module_name(shared_lib_handle
->module
));
885 if (!g_module_symbol(shared_lib_handle
->module
, "__start___bt_plugin_component_class_descriptors",
886 (gpointer
*) &cc_descriptors_begin
)) {
887 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
888 "__start___bt_plugin_component_class_descriptors",
889 g_module_name(shared_lib_handle
->module
));
892 if (!g_module_symbol(shared_lib_handle
->module
, "__stop___bt_plugin_component_class_descriptors",
893 (gpointer
*) &cc_descriptors_end
)) {
894 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
895 "__stop___bt_plugin_component_class_descriptors",
896 g_module_name(shared_lib_handle
->module
));
899 if ((!!cc_descriptors_begin
- !!cc_descriptors_end
) != 0) {
900 printf_verbose("Found __start___bt_plugin_component_class_descriptors or __stop___bt_plugin_component_class_descriptors symbol, but not both in %s\n",
901 g_module_name(shared_lib_handle
->module
));
905 if (!g_module_symbol(shared_lib_handle
->module
, "__start___bt_plugin_component_class_descriptor_attributes",
906 (gpointer
*) &cc_descr_attrs_begin
)) {
907 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
908 "__start___bt_plugin_component_class_descriptor_attributes",
909 g_module_name(shared_lib_handle
->module
));
912 if (!g_module_symbol(shared_lib_handle
->module
, "__stop___bt_plugin_component_class_descriptor_attributes",
913 (gpointer
*) &cc_descr_attrs_end
)) {
914 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
915 "__stop___bt_plugin_component_class_descriptor_attributes",
916 g_module_name(shared_lib_handle
->module
));
919 if ((!!cc_descr_attrs_begin
- !!cc_descr_attrs_end
) != 0) {
920 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",
921 g_module_name(shared_lib_handle
->module
));
925 /* Initialize plugin */
926 plugin_set
= bt_plugin_so_create_all_from_sections(shared_lib_handle
,
927 descriptors_begin
, descriptors_end
, attrs_begin
, attrs_end
,
928 cc_descriptors_begin
, cc_descriptors_end
,
929 cc_descr_attrs_begin
, cc_descr_attrs_end
);
932 BT_PUT(shared_lib_handle
);
937 void plugin_comp_class_destroy_listener(struct bt_component_class
*comp_class
,
940 gboolean exists
= g_hash_table_remove(comp_classes_to_shlib_handles
,
946 void bt_plugin_so_on_add_component_class(struct bt_plugin
*plugin
,
947 struct bt_component_class
*comp_class
)
949 struct bt_plugin_so_spec_data
*spec
= plugin
->spec_data
;
951 assert(plugin
->spec_data
);
952 assert(plugin
->type
== BT_PLUGIN_TYPE_SO
);
954 /* Map component class pointer to shared lib handle in global HT */
955 g_hash_table_insert(comp_classes_to_shlib_handles
, comp_class
,
956 bt_get(spec
->shared_lib_handle
));
958 /* Add our custom destroy listener */
959 bt_component_class_add_destroy_listener(comp_class
,
960 plugin_comp_class_destroy_listener
, NULL
);