lib: introduce bt_message_iterator_class
[babeltrace.git] / src / lib / plugin / plugin-so.c
1 /*
2 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
3 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 *
5 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
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
23 * SOFTWARE.
24 */
25
26 #define BT_LOG_TAG "LIB/PLUGIN-SO"
27 #include "lib/logging.h"
28
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"
40 #include <string.h>
41 #include <stdbool.h>
42 #include <stdlib.h>
43 #include <glib.h>
44 #include <gmodule.h>
45
46 #include "plugin.h"
47 #include "plugin-so.h"
48 #include "lib/func-status.h"
49 #include "common/common.h"
50
51 #define NATIVE_PLUGIN_SUFFIX "." G_MODULE_SUFFIX
52 #define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
53 #define LIBTOOL_PLUGIN_SUFFIX ".la"
54 #define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
55
56 #define PLUGIN_SUFFIX_LEN bt_max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
57 sizeof(LIBTOOL_PLUGIN_SUFFIX))
58
59 BT_PLUGIN_MODULE();
60
61 /*
62 * This list, global to the library, keeps all component classes that
63 * have a reference to their shared library handles. It allows iteration
64 * on all component classes still present when the destructor executes
65 * to release the shared library handle references they might still have.
66 *
67 * The list items are the component classes created with
68 * bt_plugin_add_component_class(). They keep the shared library handle
69 * object created by their plugin alive so that the plugin's code is
70 * not discarded when it could still be in use by living components
71 * created from those component classes:
72 *
73 * [component] --ref-> [component class]-> [shlib handle]
74 *
75 * It allows this use-case:
76 *
77 * my_plugins = bt_plugin_find_all_from_file("/path/to/my-plugin.so");
78 * // instantiate components from a plugin's component classes
79 * // put plugins and free my_plugins here
80 * // user code of instantiated components still exists
81 *
82 * An entry is removed from this list when a component class is
83 * destroyed thanks to a custom destroy listener. When the entry is
84 * removed, the entry is removed from the list, and we release the
85 * reference on the shlib handle. Assuming the original plugin object
86 * which contained some component classes is put first, when the last
87 * component class is removed from this list, the shared library handle
88 * object's reference count falls to zero and the shared library is
89 * finally closed.
90 */
91
92 static
93 BT_LIST_HEAD(component_class_list);
94
95 __attribute__((destructor)) static
96 void fini_comp_class_list(void)
97 {
98 struct bt_component_class *comp_class, *tmp;
99
100 bt_list_for_each_entry_safe(comp_class, tmp, &component_class_list, node) {
101 bt_list_del(&comp_class->node);
102 BT_OBJECT_PUT_REF_AND_RESET(comp_class->so_handle);
103 }
104
105 BT_LOGD_STR("Released references from all component classes to shared library handles.");
106 }
107
108 static
109 void bt_plugin_so_shared_lib_handle_destroy(struct bt_object *obj)
110 {
111 struct bt_plugin_so_shared_lib_handle *shared_lib_handle;
112
113 BT_ASSERT(obj);
114 shared_lib_handle = container_of(obj,
115 struct bt_plugin_so_shared_lib_handle, base);
116 const char *path = shared_lib_handle->path ?
117 shared_lib_handle->path->str : NULL;
118
119 BT_LOGI("Destroying shared library handle: addr=%p, path=\"%s\"",
120 shared_lib_handle, path);
121
122 if (shared_lib_handle->init_called && shared_lib_handle->exit) {
123 BT_LOGD_STR("Calling user's plugin exit function.");
124 shared_lib_handle->exit();
125 BT_LOGD_STR("User function returned.");
126 }
127
128 if (shared_lib_handle->module) {
129 #ifdef BT_DEBUG_MODE
130 /*
131 * Valgrind shows incomplete stack traces when
132 * dynamically loaded libraries are closed before it
133 * finishes. Use the LIBBABELTRACE2_NO_DLCLOSE in a debug
134 * build to avoid this.
135 */
136 const char *var = getenv("LIBBABELTRACE2_NO_DLCLOSE");
137
138 if (!var || strcmp(var, "1") != 0) {
139 #endif
140 BT_LOGI("Closing GModule: path=\"%s\"", path);
141
142 if (!g_module_close(shared_lib_handle->module)) {
143 /*
144 * Just log here: we're in a destructor,
145 * so we cannot append an error cause
146 * (there's no returned status).
147 */
148 BT_LOGE("Cannot close GModule: %s: path=\"%s\"",
149 g_module_error(), path);
150 }
151
152 shared_lib_handle->module = NULL;
153 #ifdef BT_DEBUG_MODE
154 } else {
155 BT_LOGI("Not closing GModule because `LIBBABELTRACE2_NO_DLCLOSE=1`: "
156 "path=\"%s\"", path);
157 }
158 #endif
159 }
160
161 if (shared_lib_handle->path) {
162 g_string_free(shared_lib_handle->path, TRUE);
163 shared_lib_handle->path = NULL;
164 }
165
166 g_free(shared_lib_handle);
167 }
168
169 static
170 int bt_plugin_so_shared_lib_handle_create(
171 const char *path,
172 struct bt_plugin_so_shared_lib_handle **shared_lib_handle)
173 {
174 int status = BT_FUNC_STATUS_OK;
175
176 BT_ASSERT(shared_lib_handle);
177 BT_LOGI("Creating shared library handle: path=\"%s\"", path);
178 *shared_lib_handle = g_new0(struct bt_plugin_so_shared_lib_handle, 1);
179 if (!*shared_lib_handle) {
180 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one shared library handle.");
181 status = BT_FUNC_STATUS_MEMORY_ERROR;
182 goto end;
183 }
184
185 bt_object_init_shared(&(*shared_lib_handle)->base,
186 bt_plugin_so_shared_lib_handle_destroy);
187
188 if (!path) {
189 goto end;
190 }
191
192 (*shared_lib_handle)->path = g_string_new(path);
193 if (!(*shared_lib_handle)->path) {
194 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
195 status = BT_FUNC_STATUS_MEMORY_ERROR;
196 goto end;
197 }
198
199 (*shared_lib_handle)->module = g_module_open(path, G_MODULE_BIND_LOCAL);
200 if (!(*shared_lib_handle)->module) {
201 /*
202 * INFO-level logging because we're only _trying_ to
203 * open this file as a Babeltrace plugin: if it's not,
204 * it's not an error. And because this can be tried
205 * during bt_plugin_find_all_from_dir(), it's not even a
206 * warning.
207 */
208 BT_LOGI("Cannot open GModule: %s: path=\"%s\"",
209 g_module_error(), path);
210 BT_OBJECT_PUT_REF_AND_RESET(*shared_lib_handle);
211 status = BT_FUNC_STATUS_NOT_FOUND;
212 goto end;
213 }
214
215 goto end;
216
217 end:
218 BT_ASSERT(*shared_lib_handle || status != BT_FUNC_STATUS_OK);
219 if (*shared_lib_handle) {
220 BT_LOGI("Created shared library handle: path=\"%s\", addr=%p",
221 path, *shared_lib_handle);
222 }
223
224 return status;
225 }
226
227 static
228 void bt_plugin_so_destroy_spec_data(struct bt_plugin *plugin)
229 {
230 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
231
232 if (!plugin->spec_data) {
233 return;
234 }
235
236 BT_ASSERT(plugin->type == BT_PLUGIN_TYPE_SO);
237 BT_ASSERT(spec);
238 BT_OBJECT_PUT_REF_AND_RESET(spec->shared_lib_handle);
239 g_free(plugin->spec_data);
240 plugin->spec_data = NULL;
241 }
242
243 /*
244 * This function does the following:
245 *
246 * 1. Iterate on the plugin descriptor attributes section and set the
247 * plugin's attributes depending on the attribute types. This
248 * includes the name of the plugin, its description, and its
249 * initialization function, for example.
250 *
251 * 2. Iterate on the component class descriptors section and create one
252 * "full descriptor" (temporary structure) for each one that is found
253 * and attached to our plugin descriptor.
254 *
255 * 3. Iterate on the component class descriptor attributes section and
256 * set the corresponding full descriptor's attributes depending on
257 * the attribute types. This includes the description of the
258 * component class, as well as its initialization and destroy
259 * methods.
260 *
261 * 4. Call the user's plugin initialization function, if any is
262 * defined.
263 *
264 * 5. For each full component class descriptor, create a component class
265 * object, set its optional attributes, and add it to the plugin
266 * object.
267 *
268 * 6. Freeze the plugin object.
269 */
270 static
271 int bt_plugin_so_init(struct bt_plugin *plugin,
272 bool fail_on_load_error,
273 const struct __bt_plugin_descriptor *descriptor,
274 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
275 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
276 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
277 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
278 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
279 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
280 {
281 /*
282 * This structure's members point to the plugin's memory
283 * (do NOT free).
284 */
285 struct comp_class_full_descriptor {
286 const struct __bt_plugin_component_class_descriptor *descriptor;
287 const char *description;
288 const char *help;
289
290 union {
291 struct {
292 bt_component_class_source_get_supported_mip_versions_method get_supported_mip_versions;
293 bt_component_class_source_initialize_method init;
294 bt_component_class_source_finalize_method finalize;
295 bt_component_class_source_query_method query;
296 bt_component_class_source_output_port_connected_method output_port_connected;
297 bt_message_iterator_class_initialize_method msg_iter_initialize;
298 bt_message_iterator_class_finalize_method msg_iter_finalize;
299 bt_message_iterator_class_seek_ns_from_origin_method msg_iter_seek_ns_from_origin;
300 bt_message_iterator_class_seek_beginning_method msg_iter_seek_beginning;
301 bt_message_iterator_class_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin;
302 bt_message_iterator_class_can_seek_beginning_method msg_iter_can_seek_beginning;
303 } source;
304
305 struct {
306 bt_component_class_filter_get_supported_mip_versions_method get_supported_mip_versions;
307 bt_component_class_filter_initialize_method init;
308 bt_component_class_filter_finalize_method finalize;
309 bt_component_class_filter_query_method query;
310 bt_component_class_filter_input_port_connected_method input_port_connected;
311 bt_component_class_filter_output_port_connected_method output_port_connected;
312 bt_message_iterator_class_initialize_method msg_iter_initialize;
313 bt_message_iterator_class_finalize_method msg_iter_finalize;
314 bt_message_iterator_class_seek_ns_from_origin_method msg_iter_seek_ns_from_origin;
315 bt_message_iterator_class_seek_beginning_method msg_iter_seek_beginning;
316 bt_message_iterator_class_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin;
317 bt_message_iterator_class_can_seek_beginning_method msg_iter_can_seek_beginning;
318 } filter;
319
320 struct {
321 bt_component_class_sink_get_supported_mip_versions_method get_supported_mip_versions;
322 bt_component_class_sink_initialize_method init;
323 bt_component_class_sink_finalize_method finalize;
324 bt_component_class_sink_query_method query;
325 bt_component_class_sink_input_port_connected_method input_port_connected;
326 bt_component_class_sink_graph_is_configured_method graph_is_configured;
327 } sink;
328 } methods;
329 };
330
331 int status = BT_FUNC_STATUS_OK;
332 struct __bt_plugin_descriptor_attribute const * const *cur_attr_ptr;
333 struct __bt_plugin_component_class_descriptor const * const *cur_cc_descr_ptr;
334 struct __bt_plugin_component_class_descriptor_attribute const * const *cur_cc_descr_attr_ptr;
335 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
336 GArray *comp_class_full_descriptors;
337 size_t i;
338 int ret;
339 struct bt_message_iterator_class *msg_iter_class = NULL;
340
341 BT_LOGI("Initializing plugin object from descriptors found in sections: "
342 "plugin-addr=%p, plugin-path=\"%s\", "
343 "attrs-begin-addr=%p, attrs-end-addr=%p, "
344 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
345 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p",
346 plugin,
347 spec->shared_lib_handle->path ?
348 spec->shared_lib_handle->path->str : NULL,
349 attrs_begin, attrs_end,
350 cc_descriptors_begin, cc_descriptors_end,
351 cc_descr_attrs_begin, cc_descr_attrs_end);
352 comp_class_full_descriptors = g_array_new(FALSE, TRUE,
353 sizeof(struct comp_class_full_descriptor));
354 if (!comp_class_full_descriptors) {
355 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
356 status = BT_FUNC_STATUS_MEMORY_ERROR;
357 goto end;
358 }
359
360 /* Set mandatory attributes */
361 spec->descriptor = descriptor;
362 bt_plugin_set_name(plugin, descriptor->name);
363
364 /*
365 * Find and set optional attributes attached to this plugin
366 * descriptor.
367 */
368 for (cur_attr_ptr = attrs_begin; cur_attr_ptr != attrs_end; cur_attr_ptr++) {
369 const struct __bt_plugin_descriptor_attribute *cur_attr =
370 *cur_attr_ptr;
371
372 if (!cur_attr) {
373 continue;
374 }
375
376 if (cur_attr->plugin_descriptor != descriptor) {
377 continue;
378 }
379
380 switch (cur_attr->type) {
381 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT:
382 spec->init = cur_attr->value.init;
383 break;
384 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT:
385 spec->shared_lib_handle->exit = cur_attr->value.exit;
386 break;
387 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR:
388 bt_plugin_set_author(plugin, cur_attr->value.author);
389 break;
390 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE:
391 bt_plugin_set_license(plugin, cur_attr->value.license);
392 break;
393 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
394 bt_plugin_set_description(plugin, cur_attr->value.description);
395 break;
396 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION:
397 bt_plugin_set_version(plugin,
398 (unsigned int) cur_attr->value.version.major,
399 (unsigned int) cur_attr->value.version.minor,
400 (unsigned int) cur_attr->value.version.patch,
401 cur_attr->value.version.extra);
402 break;
403 default:
404 if (fail_on_load_error) {
405 BT_LIB_LOGW_APPEND_CAUSE(
406 "Unknown plugin descriptor attribute: "
407 "plugin-path=\"%s\", plugin-name=\"%s\", "
408 "attr-type-name=\"%s\", attr-type-id=%d",
409 spec->shared_lib_handle->path ?
410 spec->shared_lib_handle->path->str :
411 NULL,
412 descriptor->name, cur_attr->type_name,
413 cur_attr->type);
414 status = BT_FUNC_STATUS_ERROR;
415 goto end;
416 } else {
417 BT_LIB_LOGW(
418 "Ignoring unknown plugin descriptor attribute: "
419 "plugin-path=\"%s\", plugin-name=\"%s\", "
420 "attr-type-name=\"%s\", attr-type-id=%d",
421 spec->shared_lib_handle->path ?
422 spec->shared_lib_handle->path->str :
423 NULL,
424 descriptor->name, cur_attr->type_name,
425 cur_attr->type);
426 }
427
428 break;
429 }
430 }
431
432 /*
433 * Find component class descriptors attached to this plugin
434 * descriptor and initialize corresponding full component class
435 * descriptors in the array.
436 */
437 for (cur_cc_descr_ptr = cc_descriptors_begin; cur_cc_descr_ptr != cc_descriptors_end; cur_cc_descr_ptr++) {
438 const struct __bt_plugin_component_class_descriptor *cur_cc_descr =
439 *cur_cc_descr_ptr;
440 struct comp_class_full_descriptor full_descriptor = {0};
441
442 if (!cur_cc_descr) {
443 continue;
444 }
445
446 if (cur_cc_descr->plugin_descriptor != descriptor) {
447 continue;
448 }
449
450 full_descriptor.descriptor = cur_cc_descr;
451 g_array_append_val(comp_class_full_descriptors,
452 full_descriptor);
453 }
454
455 /*
456 * Find component class descriptor attributes attached to this
457 * plugin descriptor and update corresponding full component
458 * class descriptors in the array.
459 */
460 for (cur_cc_descr_attr_ptr = cc_descr_attrs_begin; cur_cc_descr_attr_ptr != cc_descr_attrs_end; cur_cc_descr_attr_ptr++) {
461 const struct __bt_plugin_component_class_descriptor_attribute *cur_cc_descr_attr =
462 *cur_cc_descr_attr_ptr;
463 enum bt_component_class_type cc_type;
464
465 if (!cur_cc_descr_attr) {
466 continue;
467 }
468
469 if (cur_cc_descr_attr->comp_class_descriptor->plugin_descriptor !=
470 descriptor) {
471 continue;
472 }
473
474 cc_type = cur_cc_descr_attr->comp_class_descriptor->type;
475
476 /* Find the corresponding component class descriptor entry */
477 for (i = 0; i < comp_class_full_descriptors->len; i++) {
478 struct comp_class_full_descriptor *cc_full_descr =
479 &g_array_index(comp_class_full_descriptors,
480 struct comp_class_full_descriptor, i);
481
482 if (cur_cc_descr_attr->comp_class_descriptor !=
483 cc_full_descr->descriptor) {
484 continue;
485 }
486
487 switch (cur_cc_descr_attr->type) {
488 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
489 cc_full_descr->description =
490 cur_cc_descr_attr->value.description;
491 break;
492 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP:
493 cc_full_descr->help =
494 cur_cc_descr_attr->value.help;
495 break;
496 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GET_SUPPORTED_MIP_VERSIONS_METHOD:
497 switch (cc_type) {
498 case BT_COMPONENT_CLASS_TYPE_SOURCE:
499 cc_full_descr->methods.source.get_supported_mip_versions =
500 cur_cc_descr_attr->value.source_get_supported_mip_versions_method;
501 break;
502 case BT_COMPONENT_CLASS_TYPE_FILTER:
503 cc_full_descr->methods.filter.get_supported_mip_versions =
504 cur_cc_descr_attr->value.filter_get_supported_mip_versions_method;
505 break;
506 case BT_COMPONENT_CLASS_TYPE_SINK:
507 cc_full_descr->methods.sink.get_supported_mip_versions =
508 cur_cc_descr_attr->value.sink_get_supported_mip_versions_method;
509 break;
510 default:
511 bt_common_abort();
512 }
513 break;
514 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INITIALIZE_METHOD:
515 switch (cc_type) {
516 case BT_COMPONENT_CLASS_TYPE_SOURCE:
517 cc_full_descr->methods.source.init =
518 cur_cc_descr_attr->value.source_initialize_method;
519 break;
520 case BT_COMPONENT_CLASS_TYPE_FILTER:
521 cc_full_descr->methods.filter.init =
522 cur_cc_descr_attr->value.filter_initialize_method;
523 break;
524 case BT_COMPONENT_CLASS_TYPE_SINK:
525 cc_full_descr->methods.sink.init =
526 cur_cc_descr_attr->value.sink_initialize_method;
527 break;
528 default:
529 bt_common_abort();
530 }
531 break;
532 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD:
533 switch (cc_type) {
534 case BT_COMPONENT_CLASS_TYPE_SOURCE:
535 cc_full_descr->methods.source.finalize =
536 cur_cc_descr_attr->value.source_finalize_method;
537 break;
538 case BT_COMPONENT_CLASS_TYPE_FILTER:
539 cc_full_descr->methods.filter.finalize =
540 cur_cc_descr_attr->value.filter_finalize_method;
541 break;
542 case BT_COMPONENT_CLASS_TYPE_SINK:
543 cc_full_descr->methods.sink.finalize =
544 cur_cc_descr_attr->value.sink_finalize_method;
545 break;
546 default:
547 bt_common_abort();
548 }
549 break;
550 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD:
551 switch (cc_type) {
552 case BT_COMPONENT_CLASS_TYPE_SOURCE:
553 cc_full_descr->methods.source.query =
554 cur_cc_descr_attr->value.source_query_method;
555 break;
556 case BT_COMPONENT_CLASS_TYPE_FILTER:
557 cc_full_descr->methods.filter.query =
558 cur_cc_descr_attr->value.filter_query_method;
559 break;
560 case BT_COMPONENT_CLASS_TYPE_SINK:
561 cc_full_descr->methods.sink.query =
562 cur_cc_descr_attr->value.sink_query_method;
563 break;
564 default:
565 bt_common_abort();
566 }
567 break;
568 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INPUT_PORT_CONNECTED_METHOD:
569 switch (cc_type) {
570 case BT_COMPONENT_CLASS_TYPE_FILTER:
571 cc_full_descr->methods.filter.input_port_connected =
572 cur_cc_descr_attr->value.filter_input_port_connected_method;
573 break;
574 case BT_COMPONENT_CLASS_TYPE_SINK:
575 cc_full_descr->methods.sink.input_port_connected =
576 cur_cc_descr_attr->value.sink_input_port_connected_method;
577 break;
578 default:
579 bt_common_abort();
580 }
581 break;
582 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_OUTPUT_PORT_CONNECTED_METHOD:
583 switch (cc_type) {
584 case BT_COMPONENT_CLASS_TYPE_SOURCE:
585 cc_full_descr->methods.source.output_port_connected =
586 cur_cc_descr_attr->value.source_output_port_connected_method;
587 break;
588 case BT_COMPONENT_CLASS_TYPE_FILTER:
589 cc_full_descr->methods.filter.output_port_connected =
590 cur_cc_descr_attr->value.filter_output_port_connected_method;
591 break;
592 default:
593 bt_common_abort();
594 }
595 break;
596 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GRAPH_IS_CONFIGURED_METHOD:
597 switch (cc_type) {
598 case BT_COMPONENT_CLASS_TYPE_SINK:
599 cc_full_descr->methods.sink.graph_is_configured =
600 cur_cc_descr_attr->value.sink_graph_is_configured_method;
601 break;
602 default:
603 bt_common_abort();
604 }
605 break;
606 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_INITIALIZE_METHOD:
607 switch (cc_type) {
608 case BT_COMPONENT_CLASS_TYPE_SOURCE:
609 cc_full_descr->methods.source.msg_iter_initialize =
610 cur_cc_descr_attr->value.msg_iter_initialize_method;
611 break;
612 case BT_COMPONENT_CLASS_TYPE_FILTER:
613 cc_full_descr->methods.filter.msg_iter_initialize =
614 cur_cc_descr_attr->value.msg_iter_initialize_method;
615 break;
616 default:
617 bt_common_abort();
618 }
619 break;
620 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_FINALIZE_METHOD:
621 switch (cc_type) {
622 case BT_COMPONENT_CLASS_TYPE_SOURCE:
623 cc_full_descr->methods.source.msg_iter_finalize =
624 cur_cc_descr_attr->value.msg_iter_finalize_method;
625 break;
626 case BT_COMPONENT_CLASS_TYPE_FILTER:
627 cc_full_descr->methods.filter.msg_iter_finalize =
628 cur_cc_descr_attr->value.msg_iter_finalize_method;
629 break;
630 default:
631 bt_common_abort();
632 }
633 break;
634 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_NS_FROM_ORIGIN_METHOD:
635 switch (cc_type) {
636 case BT_COMPONENT_CLASS_TYPE_SOURCE:
637 cc_full_descr->methods.source.msg_iter_seek_ns_from_origin =
638 cur_cc_descr_attr->value.msg_iter_seek_ns_from_origin_method;
639 break;
640 case BT_COMPONENT_CLASS_TYPE_FILTER:
641 cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin =
642 cur_cc_descr_attr->value.msg_iter_seek_ns_from_origin_method;
643 break;
644 default:
645 bt_common_abort();
646 }
647 break;
648 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_BEGINNING_METHOD:
649 switch (cc_type) {
650 case BT_COMPONENT_CLASS_TYPE_SOURCE:
651 cc_full_descr->methods.source.msg_iter_seek_beginning =
652 cur_cc_descr_attr->value.msg_iter_seek_beginning_method;
653 break;
654 case BT_COMPONENT_CLASS_TYPE_FILTER:
655 cc_full_descr->methods.filter.msg_iter_seek_beginning =
656 cur_cc_descr_attr->value.msg_iter_seek_beginning_method;
657 break;
658 default:
659 bt_common_abort();
660 }
661 break;
662 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_NS_FROM_ORIGIN_METHOD:
663 switch (cc_type) {
664 case BT_COMPONENT_CLASS_TYPE_SOURCE:
665 cc_full_descr->methods.source.msg_iter_can_seek_ns_from_origin =
666 cur_cc_descr_attr->value.msg_iter_can_seek_ns_from_origin_method;
667 break;
668 case BT_COMPONENT_CLASS_TYPE_FILTER:
669 cc_full_descr->methods.filter.msg_iter_can_seek_ns_from_origin =
670 cur_cc_descr_attr->value.msg_iter_can_seek_ns_from_origin_method;
671 break;
672 default:
673 bt_common_abort();
674 }
675 break;
676 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_BEGINNING_METHOD:
677 switch (cc_type) {
678 case BT_COMPONENT_CLASS_TYPE_SOURCE:
679 cc_full_descr->methods.source.msg_iter_can_seek_beginning =
680 cur_cc_descr_attr->value.msg_iter_can_seek_beginning_method;
681 break;
682 case BT_COMPONENT_CLASS_TYPE_FILTER:
683 cc_full_descr->methods.filter.msg_iter_can_seek_beginning =
684 cur_cc_descr_attr->value.msg_iter_can_seek_beginning_method;
685 break;
686 default:
687 bt_common_abort();
688 }
689 break;
690 default:
691 if (fail_on_load_error) {
692 BT_LIB_LOGW_APPEND_CAUSE(
693 "Unknown component class descriptor attribute: "
694 "plugin-path=\"%s\", "
695 "plugin-name=\"%s\", "
696 "comp-class-name=\"%s\", "
697 "comp-class-type=%s, "
698 "attr-type-name=\"%s\", "
699 "attr-type-id=%d",
700 spec->shared_lib_handle->path ?
701 spec->shared_lib_handle->path->str :
702 NULL,
703 descriptor->name,
704 cur_cc_descr_attr->comp_class_descriptor->name,
705 bt_component_class_type_string(
706 cur_cc_descr_attr->comp_class_descriptor->type),
707 cur_cc_descr_attr->type_name,
708 cur_cc_descr_attr->type);
709 status = BT_FUNC_STATUS_ERROR;
710 goto end;
711 } else {
712 BT_LIB_LOGW(
713 "Ignoring unknown component class descriptor attribute: "
714 "plugin-path=\"%s\", "
715 "plugin-name=\"%s\", "
716 "comp-class-name=\"%s\", "
717 "comp-class-type=%s, "
718 "attr-type-name=\"%s\", "
719 "attr-type-id=%d",
720 spec->shared_lib_handle->path ?
721 spec->shared_lib_handle->path->str :
722 NULL,
723 descriptor->name,
724 cur_cc_descr_attr->comp_class_descriptor->name,
725 bt_component_class_type_string(
726 cur_cc_descr_attr->comp_class_descriptor->type),
727 cur_cc_descr_attr->type_name,
728 cur_cc_descr_attr->type);
729 }
730
731 break;
732 }
733 }
734 }
735
736 /* Initialize plugin */
737 if (spec->init) {
738 enum bt_plugin_initialize_func_status init_status;
739
740 BT_LOGD_STR("Calling user's plugin initialization function.");
741 init_status = spec->init((void *) plugin);
742 BT_LOGD("User function returned: status=%s",
743 bt_common_func_status_string(init_status));
744
745 if (init_status < 0) {
746 if (fail_on_load_error) {
747 BT_LIB_LOGW_APPEND_CAUSE(
748 "User's plugin initialization function failed: "
749 "status=%s",
750 bt_common_func_status_string(init_status));
751 status = init_status;
752 goto end;
753 } else {
754 BT_LIB_LOGW(
755 "User's plugin initialization function failed: "
756 "status=%s",
757 bt_common_func_status_string(init_status));
758 status = BT_FUNC_STATUS_NOT_FOUND;
759 }
760
761 goto end;
762 }
763 }
764
765 spec->shared_lib_handle->init_called = BT_TRUE;
766
767 /* Add described component classes to plugin */
768 for (i = 0; i < comp_class_full_descriptors->len; i++) {
769 struct comp_class_full_descriptor *cc_full_descr =
770 &g_array_index(comp_class_full_descriptors,
771 struct comp_class_full_descriptor, i);
772 struct bt_component_class *comp_class = NULL;
773 struct bt_component_class_source *src_comp_class = NULL;
774 struct bt_component_class_filter *flt_comp_class = NULL;
775 struct bt_component_class_sink *sink_comp_class = NULL;
776
777 BT_LOGI("Creating and setting properties of plugin's component class: "
778 "plugin-path=\"%s\", plugin-name=\"%s\", "
779 "comp-class-name=\"%s\", comp-class-type=%s",
780 spec->shared_lib_handle->path ?
781 spec->shared_lib_handle->path->str :
782 NULL,
783 descriptor->name,
784 cc_full_descr->descriptor->name,
785 bt_component_class_type_string(
786 cc_full_descr->descriptor->type));
787
788 if (cc_full_descr->descriptor->type == BT_COMPONENT_CLASS_TYPE_SOURCE ||
789 cc_full_descr->descriptor->type == BT_COMPONENT_CLASS_TYPE_FILTER) {
790 bt_message_iterator_class_next_method next_method;
791 bt_message_iterator_class_initialize_method init_method;
792 bt_message_iterator_class_finalize_method fini_method;
793 bt_message_iterator_class_seek_ns_from_origin_method seek_ns_from_origin_method;
794 bt_message_iterator_class_seek_beginning_method seek_beginning_method;
795 bt_message_iterator_class_can_seek_ns_from_origin_method can_seek_ns_from_origin_method;
796 bt_message_iterator_class_can_seek_beginning_method can_seek_beginning_method;
797
798 if (cc_full_descr->descriptor->type == BT_COMPONENT_CLASS_TYPE_SOURCE) {
799 next_method = cc_full_descr->descriptor->methods.source.msg_iter_next;
800 init_method = cc_full_descr->methods.source.msg_iter_initialize;
801 fini_method = cc_full_descr->methods.source.msg_iter_finalize;
802 seek_ns_from_origin_method = cc_full_descr->methods.source.msg_iter_seek_ns_from_origin;
803 can_seek_ns_from_origin_method = cc_full_descr->methods.source.msg_iter_can_seek_ns_from_origin;
804 seek_beginning_method = cc_full_descr->methods.source.msg_iter_seek_beginning;
805 can_seek_beginning_method = cc_full_descr->methods.source.msg_iter_can_seek_beginning;
806 } else {
807 next_method = cc_full_descr->descriptor->methods.filter.msg_iter_next;
808 init_method = cc_full_descr->methods.filter.msg_iter_initialize;
809 fini_method = cc_full_descr->methods.filter.msg_iter_finalize;
810 seek_ns_from_origin_method = cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin;
811 can_seek_ns_from_origin_method = cc_full_descr->methods.filter.msg_iter_can_seek_ns_from_origin;
812 seek_beginning_method = cc_full_descr->methods.filter.msg_iter_seek_beginning;
813 can_seek_beginning_method = cc_full_descr->methods.filter.msg_iter_can_seek_beginning;
814 }
815
816 msg_iter_class = bt_message_iterator_class_create(next_method);
817 if (!msg_iter_class) {
818 BT_LIB_LOGE_APPEND_CAUSE(
819 "Cannot create message iterator class.");
820 status = BT_FUNC_STATUS_MEMORY_ERROR;
821 goto end;
822 }
823
824 if (init_method) {
825 ret = bt_message_iterator_class_set_initialize_method(
826 msg_iter_class, init_method);
827 if (ret) {
828 BT_LIB_LOGE_APPEND_CAUSE(
829 "Cannot set message iterator initialization method.");
830 status = BT_FUNC_STATUS_MEMORY_ERROR;
831 goto end;
832 }
833 }
834
835 if (fini_method) {
836 ret = bt_message_iterator_class_set_finalize_method(
837 msg_iter_class, fini_method);
838 if (ret) {
839 BT_LIB_LOGE_APPEND_CAUSE(
840 "Cannot set message iterator finalization method.");
841 status = BT_FUNC_STATUS_MEMORY_ERROR;
842 goto end;
843 }
844 }
845
846 if (seek_ns_from_origin_method) {
847 ret = bt_message_iterator_class_set_seek_ns_from_origin_methods(
848 msg_iter_class,
849 seek_ns_from_origin_method,
850 can_seek_ns_from_origin_method);
851 if (ret) {
852 BT_LIB_LOGE_APPEND_CAUSE(
853 "Cannot set message iterator \"seek nanoseconds from origin\" methods.");
854 status = BT_FUNC_STATUS_MEMORY_ERROR;
855 goto end;
856 }
857 }
858
859 if (seek_beginning_method) {
860 ret = bt_message_iterator_class_set_seek_beginning_methods(
861 msg_iter_class,
862 seek_beginning_method,
863 can_seek_beginning_method);
864 if (ret) {
865 BT_LIB_LOGE_APPEND_CAUSE(
866 "Cannot set message iterator \"seek beginning\" methods.");
867 status = BT_FUNC_STATUS_MEMORY_ERROR;
868 goto end;
869 }
870 }
871 }
872
873 switch (cc_full_descr->descriptor->type) {
874 case BT_COMPONENT_CLASS_TYPE_SOURCE:
875 BT_ASSERT(msg_iter_class);
876
877 src_comp_class = bt_component_class_source_create(
878 cc_full_descr->descriptor->name, msg_iter_class);
879 comp_class = bt_component_class_source_as_component_class(
880 src_comp_class);
881 break;
882 case BT_COMPONENT_CLASS_TYPE_FILTER:
883 BT_ASSERT(msg_iter_class);
884
885 flt_comp_class = bt_component_class_filter_create(
886 cc_full_descr->descriptor->name, msg_iter_class);
887 comp_class = bt_component_class_filter_as_component_class(
888 flt_comp_class);
889 break;
890 case BT_COMPONENT_CLASS_TYPE_SINK:
891 BT_ASSERT(!msg_iter_class);
892
893 sink_comp_class = bt_component_class_sink_create(
894 cc_full_descr->descriptor->name,
895 cc_full_descr->descriptor->methods.sink.consume);
896 comp_class = bt_component_class_sink_as_component_class(
897 sink_comp_class);
898 break;
899 default:
900 if (fail_on_load_error) {
901 BT_LIB_LOGW_APPEND_CAUSE(
902 "Unknown component class type: "
903 "plugin-path=\"%s\", plugin-name=\"%s\", "
904 "comp-class-name=\"%s\", comp-class-type=%d",
905 spec->shared_lib_handle->path->str ?
906 spec->shared_lib_handle->path->str :
907 NULL,
908 descriptor->name,
909 cc_full_descr->descriptor->name,
910 cc_full_descr->descriptor->type);
911 status = BT_FUNC_STATUS_ERROR;
912 goto end;
913 } else {
914 BT_LIB_LOGW(
915 "Ignoring unknown component class type: "
916 "plugin-path=\"%s\", plugin-name=\"%s\", "
917 "comp-class-name=\"%s\", comp-class-type=%d",
918 spec->shared_lib_handle->path->str ?
919 spec->shared_lib_handle->path->str :
920 NULL,
921 descriptor->name,
922 cc_full_descr->descriptor->name,
923 cc_full_descr->descriptor->type);
924 continue;
925 }
926 }
927
928 if (!comp_class) {
929 BT_LIB_LOGE_APPEND_CAUSE(
930 "Cannot create component class.");
931 status = BT_FUNC_STATUS_MEMORY_ERROR;
932 goto end;
933 }
934
935 /*
936 * The component class has taken a reference on the message
937 * iterator class, so we can drop ours. The message iterator
938 * class will get destroyed at the same time as the component
939 * class.
940 */
941 bt_message_iterator_class_put_ref(msg_iter_class);
942 msg_iter_class = NULL;
943
944 if (cc_full_descr->description) {
945 ret = bt_component_class_set_description(
946 comp_class, cc_full_descr->description);
947 if (ret) {
948 BT_LIB_LOGE_APPEND_CAUSE(
949 "Cannot set component class's description.");
950 status = BT_FUNC_STATUS_MEMORY_ERROR;
951 BT_OBJECT_PUT_REF_AND_RESET(comp_class);
952 goto end;
953 }
954 }
955
956 if (cc_full_descr->help) {
957 ret = bt_component_class_set_help(comp_class,
958 cc_full_descr->help);
959 if (ret) {
960 BT_LIB_LOGE_APPEND_CAUSE(
961 "Cannot set component class's help string.");
962 status = BT_FUNC_STATUS_MEMORY_ERROR;
963 BT_OBJECT_PUT_REF_AND_RESET(comp_class);
964 goto end;
965 }
966 }
967
968 switch (cc_full_descr->descriptor->type) {
969 case BT_COMPONENT_CLASS_TYPE_SOURCE:
970 if (cc_full_descr->methods.source.get_supported_mip_versions) {
971 ret = bt_component_class_source_set_get_supported_mip_versions_method(
972 src_comp_class,
973 cc_full_descr->methods.source.get_supported_mip_versions);
974 if (ret) {
975 BT_LIB_LOGE_APPEND_CAUSE(
976 "Cannot set source component class's \"get supported MIP versions\" method.");
977 status = BT_FUNC_STATUS_MEMORY_ERROR;
978 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
979 goto end;
980 }
981 }
982
983 if (cc_full_descr->methods.source.init) {
984 ret = bt_component_class_source_set_initialize_method(
985 src_comp_class,
986 cc_full_descr->methods.source.init);
987 if (ret) {
988 BT_LIB_LOGE_APPEND_CAUSE(
989 "Cannot set source component class's initialization method.");
990 status = BT_FUNC_STATUS_MEMORY_ERROR;
991 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
992 goto end;
993 }
994 }
995
996 if (cc_full_descr->methods.source.finalize) {
997 ret = bt_component_class_source_set_finalize_method(
998 src_comp_class,
999 cc_full_descr->methods.source.finalize);
1000 if (ret) {
1001 BT_LIB_LOGE_APPEND_CAUSE(
1002 "Cannot set source component class's finalization method.");
1003 status = BT_FUNC_STATUS_MEMORY_ERROR;
1004 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
1005 goto end;
1006 }
1007 }
1008
1009 if (cc_full_descr->methods.source.query) {
1010 ret = bt_component_class_source_set_query_method(
1011 src_comp_class,
1012 cc_full_descr->methods.source.query);
1013 if (ret) {
1014 BT_LIB_LOGE_APPEND_CAUSE(
1015 "Cannot set source component class's query method.");
1016 status = BT_FUNC_STATUS_MEMORY_ERROR;
1017 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
1018 goto end;
1019 }
1020 }
1021
1022 if (cc_full_descr->methods.source.output_port_connected) {
1023 ret = bt_component_class_source_set_output_port_connected_method(
1024 src_comp_class,
1025 cc_full_descr->methods.source.output_port_connected);
1026 if (ret) {
1027 BT_LIB_LOGE_APPEND_CAUSE(
1028 "Cannot set source component class's \"output port connected\" method.");
1029 status = BT_FUNC_STATUS_MEMORY_ERROR;
1030 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
1031 goto end;
1032 }
1033 }
1034
1035 break;
1036 case BT_COMPONENT_CLASS_TYPE_FILTER:
1037 if (cc_full_descr->methods.filter.get_supported_mip_versions) {
1038 ret = bt_component_class_filter_set_get_supported_mip_versions_method(
1039 flt_comp_class,
1040 cc_full_descr->methods.filter.get_supported_mip_versions);
1041 if (ret) {
1042 BT_LIB_LOGE_APPEND_CAUSE(
1043 "Cannot set filter component class's \"get supported MIP versions\" method.");
1044 status = BT_FUNC_STATUS_MEMORY_ERROR;
1045 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1046 goto end;
1047 }
1048 }
1049
1050 if (cc_full_descr->methods.filter.init) {
1051 ret = bt_component_class_filter_set_initialize_method(
1052 flt_comp_class,
1053 cc_full_descr->methods.filter.init);
1054 if (ret) {
1055 BT_LIB_LOGE_APPEND_CAUSE(
1056 "Cannot set filter component class's initialization method.");
1057 status = BT_FUNC_STATUS_MEMORY_ERROR;
1058 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1059 goto end;
1060 }
1061 }
1062
1063 if (cc_full_descr->methods.filter.finalize) {
1064 ret = bt_component_class_filter_set_finalize_method(
1065 flt_comp_class,
1066 cc_full_descr->methods.filter.finalize);
1067 if (ret) {
1068 BT_LIB_LOGE_APPEND_CAUSE(
1069 "Cannot set filter component class's finalization method.");
1070 status = BT_FUNC_STATUS_MEMORY_ERROR;
1071 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1072 goto end;
1073 }
1074 }
1075
1076 if (cc_full_descr->methods.filter.query) {
1077 ret = bt_component_class_filter_set_query_method(
1078 flt_comp_class,
1079 cc_full_descr->methods.filter.query);
1080 if (ret) {
1081 BT_LIB_LOGE_APPEND_CAUSE(
1082 "Cannot set filter component class's query method.");
1083 status = BT_FUNC_STATUS_MEMORY_ERROR;
1084 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1085 goto end;
1086 }
1087 }
1088
1089 if (cc_full_descr->methods.filter.input_port_connected) {
1090 ret = bt_component_class_filter_set_input_port_connected_method(
1091 flt_comp_class,
1092 cc_full_descr->methods.filter.input_port_connected);
1093 if (ret) {
1094 BT_LIB_LOGE_APPEND_CAUSE(
1095 "Cannot set filter component class's \"input port connected\" method.");
1096 status = BT_FUNC_STATUS_MEMORY_ERROR;
1097 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1098 goto end;
1099 }
1100 }
1101
1102 if (cc_full_descr->methods.filter.output_port_connected) {
1103 ret = bt_component_class_filter_set_output_port_connected_method(
1104 flt_comp_class,
1105 cc_full_descr->methods.filter.output_port_connected);
1106 if (ret) {
1107 BT_LIB_LOGE_APPEND_CAUSE(
1108 "Cannot set filter component class's \"output port connected\" method.");
1109 status = BT_FUNC_STATUS_MEMORY_ERROR;
1110 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1111 goto end;
1112 }
1113 }
1114
1115 break;
1116 case BT_COMPONENT_CLASS_TYPE_SINK:
1117 if (cc_full_descr->methods.sink.get_supported_mip_versions) {
1118 ret = bt_component_class_sink_set_get_supported_mip_versions_method(
1119 sink_comp_class,
1120 cc_full_descr->methods.sink.get_supported_mip_versions);
1121 if (ret) {
1122 BT_LIB_LOGE_APPEND_CAUSE(
1123 "Cannot set sink component class's \"get supported MIP versions\" method.");
1124 status = BT_FUNC_STATUS_MEMORY_ERROR;
1125 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1126 goto end;
1127 }
1128 }
1129
1130 if (cc_full_descr->methods.sink.init) {
1131 ret = bt_component_class_sink_set_initialize_method(
1132 sink_comp_class,
1133 cc_full_descr->methods.sink.init);
1134 if (ret) {
1135 BT_LIB_LOGE_APPEND_CAUSE(
1136 "Cannot set sink component class's initialization method.");
1137 status = BT_FUNC_STATUS_MEMORY_ERROR;
1138 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1139 goto end;
1140 }
1141 }
1142
1143 if (cc_full_descr->methods.sink.finalize) {
1144 ret = bt_component_class_sink_set_finalize_method(
1145 sink_comp_class,
1146 cc_full_descr->methods.sink.finalize);
1147 if (ret) {
1148 BT_LIB_LOGE_APPEND_CAUSE(
1149 "Cannot set sink component class's finalization method.");
1150 status = BT_FUNC_STATUS_MEMORY_ERROR;
1151 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1152 goto end;
1153 }
1154 }
1155
1156 if (cc_full_descr->methods.sink.query) {
1157 ret = bt_component_class_sink_set_query_method(
1158 sink_comp_class,
1159 cc_full_descr->methods.sink.query);
1160 if (ret) {
1161 BT_LIB_LOGE_APPEND_CAUSE(
1162 "Cannot set sink component class's query method.");
1163 status = BT_FUNC_STATUS_MEMORY_ERROR;
1164 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1165 goto end;
1166 }
1167 }
1168
1169 if (cc_full_descr->methods.sink.input_port_connected) {
1170 ret = bt_component_class_sink_set_input_port_connected_method(
1171 sink_comp_class,
1172 cc_full_descr->methods.sink.input_port_connected);
1173 if (ret) {
1174 BT_LIB_LOGE_APPEND_CAUSE(
1175 "Cannot set sink component class's \"input port connected\" method.");
1176 status = BT_FUNC_STATUS_MEMORY_ERROR;
1177 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1178 goto end;
1179 }
1180 }
1181
1182 if (cc_full_descr->methods.sink.graph_is_configured) {
1183 ret = bt_component_class_sink_set_graph_is_configured_method(
1184 sink_comp_class,
1185 cc_full_descr->methods.sink.graph_is_configured);
1186 if (ret) {
1187 BT_LIB_LOGE_APPEND_CAUSE(
1188 "Cannot set sink component class's \"graph is configured\" method.");
1189 status = BT_FUNC_STATUS_MEMORY_ERROR;
1190 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1191 goto end;
1192 }
1193 }
1194
1195 break;
1196 default:
1197 bt_common_abort();
1198 }
1199
1200 /*
1201 * Add component class to the plugin object.
1202 *
1203 * This will call back
1204 * bt_plugin_so_on_add_component_class() so that we can
1205 * add a mapping in the component class list when we
1206 * know the component class is successfully added.
1207 */
1208 status = bt_plugin_add_component_class(plugin,
1209 (void *) comp_class);
1210 BT_OBJECT_PUT_REF_AND_RESET(comp_class);
1211 if (status < 0) {
1212 BT_LIB_LOGE_APPEND_CAUSE(
1213 "Cannot add component class to plugin.");
1214 goto end;
1215 }
1216 }
1217
1218 end:
1219 bt_message_iterator_class_put_ref(msg_iter_class);
1220 g_array_free(comp_class_full_descriptors, TRUE);
1221 return status;
1222 }
1223
1224 static
1225 struct bt_plugin *bt_plugin_so_create_empty(
1226 struct bt_plugin_so_shared_lib_handle *shared_lib_handle)
1227 {
1228 struct bt_plugin *plugin;
1229 struct bt_plugin_so_spec_data *spec;
1230
1231 plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_SO);
1232 if (!plugin) {
1233 goto error;
1234 }
1235
1236 plugin->destroy_spec_data = bt_plugin_so_destroy_spec_data;
1237 plugin->spec_data = g_new0(struct bt_plugin_so_spec_data, 1);
1238 if (!plugin->spec_data) {
1239 BT_LIB_LOGE_APPEND_CAUSE(
1240 "Failed to allocate one SO plugin specific data structure.");
1241 goto error;
1242 }
1243
1244 spec = plugin->spec_data;
1245 spec->shared_lib_handle = shared_lib_handle;
1246 bt_object_get_ref_no_null_check(spec->shared_lib_handle);
1247 goto end;
1248
1249 error:
1250 BT_OBJECT_PUT_REF_AND_RESET(plugin);
1251
1252 end:
1253 return plugin;
1254 }
1255
1256 static
1257 size_t count_non_null_items_in_section(const void *begin, const void *end)
1258 {
1259 size_t count = 0;
1260 const int * const *begin_int = (const int * const *) begin;
1261 const int * const *end_int = (const int * const *) end;
1262 const int * const *iter;
1263
1264 for (iter = begin_int; iter != end_int; iter++) {
1265 if (*iter) {
1266 count++;
1267 }
1268 }
1269
1270 return count;
1271 }
1272
1273 static
1274 int bt_plugin_so_create_all_from_sections(
1275 struct bt_plugin_so_shared_lib_handle *shared_lib_handle,
1276 bool fail_on_load_error,
1277 struct __bt_plugin_descriptor const * const *descriptors_begin,
1278 struct __bt_plugin_descriptor const * const *descriptors_end,
1279 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
1280 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
1281 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
1282 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
1283 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
1284 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end,
1285 struct bt_plugin_set **plugin_set_out)
1286 {
1287 int status = BT_FUNC_STATUS_OK;
1288 size_t descriptor_count;
1289 size_t attrs_count;
1290 size_t cc_descriptors_count;
1291 size_t cc_descr_attrs_count;
1292 size_t i;
1293
1294 BT_ASSERT(shared_lib_handle);
1295 BT_ASSERT(plugin_set_out);
1296 *plugin_set_out = NULL;
1297 descriptor_count = count_non_null_items_in_section(descriptors_begin, descriptors_end);
1298 attrs_count = count_non_null_items_in_section(attrs_begin, attrs_end);
1299 cc_descriptors_count = count_non_null_items_in_section(cc_descriptors_begin, cc_descriptors_end);
1300 cc_descr_attrs_count = count_non_null_items_in_section(cc_descr_attrs_begin, cc_descr_attrs_end);
1301 BT_LOGI("Creating all SO plugins from sections: "
1302 "plugin-path=\"%s\", "
1303 "descr-begin-addr=%p, descr-end-addr=%p, "
1304 "attrs-begin-addr=%p, attrs-end-addr=%p, "
1305 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
1306 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p, "
1307 "descr-count=%zu, attrs-count=%zu, "
1308 "cc-descr-count=%zu, cc-descr-attrs-count=%zu",
1309 shared_lib_handle->path ? shared_lib_handle->path->str : NULL,
1310 descriptors_begin, descriptors_end,
1311 attrs_begin, attrs_end,
1312 cc_descriptors_begin, cc_descriptors_end,
1313 cc_descr_attrs_begin, cc_descr_attrs_end,
1314 descriptor_count, attrs_count,
1315 cc_descriptors_count, cc_descr_attrs_count);
1316 *plugin_set_out = bt_plugin_set_create();
1317 if (!*plugin_set_out) {
1318 BT_LIB_LOGE_APPEND_CAUSE("Cannot create empty plugin set.");
1319 status = BT_FUNC_STATUS_MEMORY_ERROR;
1320 goto error;
1321 }
1322
1323 for (i = 0; i < descriptors_end - descriptors_begin; i++) {
1324 const struct __bt_plugin_descriptor *descriptor =
1325 descriptors_begin[i];
1326 struct bt_plugin *plugin;
1327
1328 if (!descriptor) {
1329 continue;
1330 }
1331
1332 BT_LOGI("Creating plugin object for plugin: name=\"%s\"",
1333 descriptor->name);
1334 plugin = bt_plugin_so_create_empty(shared_lib_handle);
1335 if (!plugin) {
1336 BT_LIB_LOGE_APPEND_CAUSE(
1337 "Cannot create empty shared library handle.");
1338 status = BT_FUNC_STATUS_MEMORY_ERROR;
1339 goto error;
1340 }
1341
1342 if (shared_lib_handle->path) {
1343 bt_plugin_set_path(plugin,
1344 shared_lib_handle->path->str);
1345 }
1346
1347 status = bt_plugin_so_init(plugin, fail_on_load_error,
1348 descriptor, attrs_begin, attrs_end,
1349 cc_descriptors_begin, cc_descriptors_end,
1350 cc_descr_attrs_begin, cc_descr_attrs_end);
1351 if (status == BT_FUNC_STATUS_OK) {
1352 /* Add to plugin set */
1353 bt_plugin_set_add_plugin(*plugin_set_out, plugin);
1354 BT_OBJECT_PUT_REF_AND_RESET(plugin);
1355 } else if (status < 0) {
1356 /*
1357 * bt_plugin_so_init() handles
1358 * `fail_on_load_error`, so this is a "real"
1359 * error.
1360 */
1361 BT_LIB_LOGW_APPEND_CAUSE(
1362 "Cannot initialize SO plugin object from sections.");
1363 BT_OBJECT_PUT_REF_AND_RESET(plugin);
1364 goto error;
1365 }
1366
1367 BT_ASSERT(!plugin);
1368 }
1369
1370 BT_ASSERT(*plugin_set_out);
1371
1372 if ((*plugin_set_out)->plugins->len == 0) {
1373 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out);
1374 status = BT_FUNC_STATUS_NOT_FOUND;
1375 }
1376
1377 goto end;
1378
1379 error:
1380 BT_ASSERT(status < 0);
1381 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out);
1382
1383 end:
1384 return status;
1385 }
1386
1387 BT_HIDDEN
1388 int bt_plugin_so_create_all_from_static(bool fail_on_load_error,
1389 struct bt_plugin_set **plugin_set_out)
1390 {
1391 int status;
1392 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
1393
1394 BT_ASSERT(plugin_set_out);
1395 *plugin_set_out = NULL;
1396 status = bt_plugin_so_shared_lib_handle_create(NULL,
1397 &shared_lib_handle);
1398 if (status != BT_FUNC_STATUS_OK) {
1399 BT_ASSERT(!shared_lib_handle);
1400 goto end;
1401 }
1402
1403 BT_ASSERT(shared_lib_handle);
1404 BT_LOGD_STR("Creating all SO plugins from built-in plugins.");
1405 status = bt_plugin_so_create_all_from_sections(shared_lib_handle,
1406 fail_on_load_error,
1407 __bt_get_begin_section_plugin_descriptors(),
1408 __bt_get_end_section_plugin_descriptors(),
1409 __bt_get_begin_section_plugin_descriptor_attributes(),
1410 __bt_get_end_section_plugin_descriptor_attributes(),
1411 __bt_get_begin_section_component_class_descriptors(),
1412 __bt_get_end_section_component_class_descriptors(),
1413 __bt_get_begin_section_component_class_descriptor_attributes(),
1414 __bt_get_end_section_component_class_descriptor_attributes(),
1415 plugin_set_out);
1416 BT_ASSERT((status == BT_FUNC_STATUS_OK && *plugin_set_out &&
1417 (*plugin_set_out)->plugins->len > 0) || !*plugin_set_out);
1418
1419 end:
1420 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle);
1421 return status;
1422 }
1423
1424 BT_HIDDEN
1425 int bt_plugin_so_create_all_from_file(const char *path,
1426 bool fail_on_load_error, struct bt_plugin_set **plugin_set_out)
1427 {
1428 size_t path_len;
1429 int status;
1430 struct __bt_plugin_descriptor const * const *descriptors_begin = NULL;
1431 struct __bt_plugin_descriptor const * const *descriptors_end = NULL;
1432 struct __bt_plugin_descriptor_attribute const * const *attrs_begin = NULL;
1433 struct __bt_plugin_descriptor_attribute const * const *attrs_end = NULL;
1434 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin = NULL;
1435 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end = NULL;
1436 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin = NULL;
1437 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end = NULL;
1438 struct __bt_plugin_descriptor const * const *(*get_begin_section_plugin_descriptors)(void);
1439 struct __bt_plugin_descriptor const * const *(*get_end_section_plugin_descriptors)(void);
1440 struct __bt_plugin_descriptor_attribute const * const *(*get_begin_section_plugin_descriptor_attributes)(void);
1441 struct __bt_plugin_descriptor_attribute const * const *(*get_end_section_plugin_descriptor_attributes)(void);
1442 struct __bt_plugin_component_class_descriptor const * const *(*get_begin_section_component_class_descriptors)(void);
1443 struct __bt_plugin_component_class_descriptor const * const *(*get_end_section_component_class_descriptors)(void);
1444 struct __bt_plugin_component_class_descriptor_attribute const * const *(*get_begin_section_component_class_descriptor_attributes)(void);
1445 struct __bt_plugin_component_class_descriptor_attribute const * const *(*get_end_section_component_class_descriptor_attributes)(void);
1446 bt_bool is_libtool_wrapper = BT_FALSE, is_shared_object = BT_FALSE;
1447 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
1448
1449 BT_ASSERT(path);
1450 BT_ASSERT(plugin_set_out);
1451 *plugin_set_out = NULL;
1452 path_len = strlen(path);
1453
1454 /*
1455 * An SO plugin file must have a known plugin file suffix. So the file
1456 * path must be longer than the suffix length.
1457 */
1458 if (path_len <= PLUGIN_SUFFIX_LEN) {
1459 BT_LOGI("Path is too short to be an `.so` or `.la` plugin file:"
1460 "path=%s, path-length=%zu, min-length=%zu",
1461 path, path_len, PLUGIN_SUFFIX_LEN);
1462 status = BT_FUNC_STATUS_NOT_FOUND;
1463 goto end;
1464 }
1465
1466 BT_LOGI("Trying to create all SO plugins from file: path=\"%s\"", path);
1467 path_len++;
1468
1469 /*
1470 * Check if the file ends with a known plugin file type suffix
1471 * (i.e. .so or .la on Linux).
1472 */
1473 is_libtool_wrapper = !strncmp(LIBTOOL_PLUGIN_SUFFIX,
1474 path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN,
1475 LIBTOOL_PLUGIN_SUFFIX_LEN);
1476 is_shared_object = !strncmp(NATIVE_PLUGIN_SUFFIX,
1477 path + path_len - NATIVE_PLUGIN_SUFFIX_LEN,
1478 NATIVE_PLUGIN_SUFFIX_LEN);
1479 if (!is_shared_object && !is_libtool_wrapper) {
1480 /* Name indicates this is not a plugin file; not an error */
1481 BT_LOGI("File is not an SO plugin file: path=\"%s\"", path);
1482 status = BT_FUNC_STATUS_NOT_FOUND;
1483 goto end;
1484 }
1485
1486 status = bt_plugin_so_shared_lib_handle_create(path,
1487 &shared_lib_handle);
1488 if (status != BT_FUNC_STATUS_OK) {
1489 /* bt_plugin_so_shared_lib_handle_create() logs more details */
1490 BT_ASSERT(!shared_lib_handle);
1491 goto end;
1492 }
1493
1494 if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_plugin_descriptors",
1495 (gpointer *) &get_begin_section_plugin_descriptors)) {
1496 descriptors_begin = get_begin_section_plugin_descriptors();
1497 } else {
1498 /*
1499 * Use this first symbol to know whether or not this
1500 * shared object _looks like_ a Babeltrace plugin. Since
1501 * g_module_symbol() failed, assume that this is not a
1502 * Babeltrace plugin, so it's not an error.
1503 */
1504 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1505 "symbol=\"%s\"", path,
1506 "__bt_get_begin_section_plugin_descriptors");
1507 status = BT_FUNC_STATUS_NOT_FOUND;
1508 goto end;
1509 }
1510
1511 /*
1512 * If g_module_symbol() fails for any of the other symbols, fail
1513 * if `fail_on_load_error` is true.
1514 */
1515 if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_plugin_descriptors",
1516 (gpointer *) &get_end_section_plugin_descriptors)) {
1517 descriptors_end = get_end_section_plugin_descriptors();
1518 } else {
1519 if (fail_on_load_error) {
1520 BT_LIB_LOGW_APPEND_CAUSE(
1521 "Cannot resolve plugin symbol: path=\"%s\", "
1522 "symbol=\"%s\"", path,
1523 "__bt_get_end_section_plugin_descriptors");
1524 status = BT_FUNC_STATUS_ERROR;
1525 } else {
1526 BT_LIB_LOGW(
1527 "Cannot resolve plugin symbol: path=\"%s\", "
1528 "symbol=\"%s\"", path,
1529 "__bt_get_end_section_plugin_descriptors");
1530 status = BT_FUNC_STATUS_NOT_FOUND;
1531 }
1532
1533 goto end;
1534 }
1535
1536 if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_plugin_descriptor_attributes",
1537 (gpointer *) &get_begin_section_plugin_descriptor_attributes)) {
1538 attrs_begin = get_begin_section_plugin_descriptor_attributes();
1539 } else {
1540 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1541 "symbol=\"%s\"", path,
1542 "__bt_get_begin_section_plugin_descriptor_attributes");
1543 }
1544
1545 if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_plugin_descriptor_attributes",
1546 (gpointer *) &get_end_section_plugin_descriptor_attributes)) {
1547 attrs_end = get_end_section_plugin_descriptor_attributes();
1548 } else {
1549 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1550 "symbol=\"%s\"", path,
1551 "__bt_get_end_section_plugin_descriptor_attributes");
1552 }
1553
1554 if ((!!attrs_begin - !!attrs_end) != 0) {
1555 if (fail_on_load_error) {
1556 BT_LIB_LOGW_APPEND_CAUSE(
1557 "Found section start or end symbol, but not both: "
1558 "path=\"%s\", symbol-start=\"%s\", "
1559 "symbol-end=\"%s\", symbol-start-addr=%p, "
1560 "symbol-end-addr=%p",
1561 path, "__bt_get_begin_section_plugin_descriptor_attributes",
1562 "__bt_get_end_section_plugin_descriptor_attributes",
1563 attrs_begin, attrs_end);
1564 status = BT_FUNC_STATUS_ERROR;
1565 } else {
1566 BT_LIB_LOGW(
1567 "Found section start or end symbol, but not both: "
1568 "path=\"%s\", symbol-start=\"%s\", "
1569 "symbol-end=\"%s\", symbol-start-addr=%p, "
1570 "symbol-end-addr=%p",
1571 path, "__bt_get_begin_section_plugin_descriptor_attributes",
1572 "__bt_get_end_section_plugin_descriptor_attributes",
1573 attrs_begin, attrs_end);
1574 status = BT_FUNC_STATUS_NOT_FOUND;
1575 }
1576
1577 goto end;
1578 }
1579
1580 if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_component_class_descriptors",
1581 (gpointer *) &get_begin_section_component_class_descriptors)) {
1582 cc_descriptors_begin = get_begin_section_component_class_descriptors();
1583 } else {
1584 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1585 "symbol=\"%s\"", path,
1586 "__bt_get_begin_section_component_class_descriptors");
1587 }
1588
1589 if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_component_class_descriptors",
1590 (gpointer *) &get_end_section_component_class_descriptors)) {
1591 cc_descriptors_end = get_end_section_component_class_descriptors();
1592 } else {
1593 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1594 "symbol=\"%s\"", path,
1595 "__bt_get_end_section_component_class_descriptors");
1596 }
1597
1598 if ((!!cc_descriptors_begin - !!cc_descriptors_end) != 0) {
1599 if (fail_on_load_error) {
1600 BT_LIB_LOGW_APPEND_CAUSE(
1601 "Found section start or end symbol, but not both: "
1602 "path=\"%s\", symbol-start=\"%s\", "
1603 "symbol-end=\"%s\", symbol-start-addr=%p, "
1604 "symbol-end-addr=%p",
1605 path, "__bt_get_begin_section_component_class_descriptors",
1606 "__bt_get_end_section_component_class_descriptors",
1607 cc_descriptors_begin, cc_descriptors_end);
1608 status = BT_FUNC_STATUS_ERROR;
1609 } else {
1610 BT_LIB_LOGW(
1611 "Found section start or end symbol, but not both: "
1612 "path=\"%s\", symbol-start=\"%s\", "
1613 "symbol-end=\"%s\", symbol-start-addr=%p, "
1614 "symbol-end-addr=%p",
1615 path, "__bt_get_begin_section_component_class_descriptors",
1616 "__bt_get_end_section_component_class_descriptors",
1617 cc_descriptors_begin, cc_descriptors_end);
1618 status = BT_FUNC_STATUS_NOT_FOUND;
1619 }
1620
1621 goto end;
1622 }
1623
1624 if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_component_class_descriptor_attributes",
1625 (gpointer *) &get_begin_section_component_class_descriptor_attributes)) {
1626 cc_descr_attrs_begin = get_begin_section_component_class_descriptor_attributes();
1627 } else {
1628 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1629 "symbol=\"%s\"", path,
1630 "__bt_get_begin_section_component_class_descriptor_attributes");
1631 }
1632
1633 if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_component_class_descriptor_attributes",
1634 (gpointer *) &get_end_section_component_class_descriptor_attributes)) {
1635 cc_descr_attrs_end = get_end_section_component_class_descriptor_attributes();
1636 } else {
1637 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1638 "symbol=\"%s\"", path,
1639 "__bt_get_end_section_component_class_descriptor_attributes");
1640 }
1641
1642 if ((!!cc_descr_attrs_begin - !!cc_descr_attrs_end) != 0) {
1643 if (fail_on_load_error) {
1644 BT_LIB_LOGW_APPEND_CAUSE(
1645 "Found section start or end symbol, but not both: "
1646 "path=\"%s\", symbol-start=\"%s\", "
1647 "symbol-end=\"%s\", symbol-start-addr=%p, "
1648 "symbol-end-addr=%p",
1649 path, "__bt_get_begin_section_component_class_descriptor_attributes",
1650 "__bt_get_end_section_component_class_descriptor_attributes",
1651 cc_descr_attrs_begin, cc_descr_attrs_end);
1652 status = BT_FUNC_STATUS_ERROR;
1653 } else {
1654 BT_LIB_LOGW(
1655 "Found section start or end symbol, but not both: "
1656 "path=\"%s\", symbol-start=\"%s\", "
1657 "symbol-end=\"%s\", symbol-start-addr=%p, "
1658 "symbol-end-addr=%p",
1659 path, "__bt_get_begin_section_component_class_descriptor_attributes",
1660 "__bt_get_end_section_component_class_descriptor_attributes",
1661 cc_descr_attrs_begin, cc_descr_attrs_end);
1662 status = BT_FUNC_STATUS_NOT_FOUND;
1663 }
1664
1665 goto end;
1666 }
1667
1668 /* Initialize plugin */
1669 BT_LOGD_STR("Initializing plugin object.");
1670 status = bt_plugin_so_create_all_from_sections(shared_lib_handle,
1671 fail_on_load_error,
1672 descriptors_begin, descriptors_end, attrs_begin, attrs_end,
1673 cc_descriptors_begin, cc_descriptors_end,
1674 cc_descr_attrs_begin, cc_descr_attrs_end, plugin_set_out);
1675
1676 end:
1677 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle);
1678 return status;
1679 }
1680
1681 static
1682 void plugin_comp_class_destroy_listener(struct bt_component_class *comp_class,
1683 void *data)
1684 {
1685 bt_list_del(&comp_class->node);
1686 BT_OBJECT_PUT_REF_AND_RESET(comp_class->so_handle);
1687 BT_LOGD("Component class destroyed: removed entry from list: "
1688 "comp-cls-addr=%p", comp_class);
1689 }
1690
1691 void bt_plugin_so_on_add_component_class(struct bt_plugin *plugin,
1692 struct bt_component_class *comp_class)
1693 {
1694 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
1695
1696 BT_ASSERT(plugin->spec_data);
1697 BT_ASSERT(plugin->type == BT_PLUGIN_TYPE_SO);
1698
1699 bt_list_add(&comp_class->node, &component_class_list);
1700 comp_class->so_handle = spec->shared_lib_handle;
1701 bt_object_get_ref_no_null_check(comp_class->so_handle);
1702
1703 /* Add our custom destroy listener */
1704 bt_component_class_add_destroy_listener(comp_class,
1705 plugin_comp_class_destroy_listener, NULL);
1706 }
This page took 0.064532 seconds and 4 git commands to generate.