Cleanup: add `#include <stdbool.h>` whenever `bool` type is used
[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_component_class_source_message_iterator_initialize_method msg_iter_initialize;
298 bt_component_class_source_message_iterator_finalize_method msg_iter_finalize;
299 bt_component_class_source_message_iterator_seek_ns_from_origin_method msg_iter_seek_ns_from_origin;
300 bt_component_class_source_message_iterator_seek_beginning_method msg_iter_seek_beginning;
301 bt_component_class_source_message_iterator_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin;
302 bt_component_class_source_message_iterator_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_component_class_filter_message_iterator_initialize_method msg_iter_initialize;
313 bt_component_class_filter_message_iterator_finalize_method msg_iter_finalize;
314 bt_component_class_filter_message_iterator_seek_ns_from_origin_method msg_iter_seek_ns_from_origin;
315 bt_component_class_filter_message_iterator_seek_beginning_method msg_iter_seek_beginning;
316 bt_component_class_filter_message_iterator_can_seek_ns_from_origin_method msg_iter_can_seek_ns_from_origin;
317 bt_component_class_filter_message_iterator_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
340 BT_LOGI("Initializing plugin object from descriptors found in sections: "
341 "plugin-addr=%p, plugin-path=\"%s\", "
342 "attrs-begin-addr=%p, attrs-end-addr=%p, "
343 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
344 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p",
345 plugin,
346 spec->shared_lib_handle->path ?
347 spec->shared_lib_handle->path->str : NULL,
348 attrs_begin, attrs_end,
349 cc_descriptors_begin, cc_descriptors_end,
350 cc_descr_attrs_begin, cc_descr_attrs_end);
351 comp_class_full_descriptors = g_array_new(FALSE, TRUE,
352 sizeof(struct comp_class_full_descriptor));
353 if (!comp_class_full_descriptors) {
354 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
355 status = BT_FUNC_STATUS_MEMORY_ERROR;
356 goto end;
357 }
358
359 /* Set mandatory attributes */
360 spec->descriptor = descriptor;
361 bt_plugin_set_name(plugin, descriptor->name);
362
363 /*
364 * Find and set optional attributes attached to this plugin
365 * descriptor.
366 */
367 for (cur_attr_ptr = attrs_begin; cur_attr_ptr != attrs_end; cur_attr_ptr++) {
368 const struct __bt_plugin_descriptor_attribute *cur_attr =
369 *cur_attr_ptr;
370
371 if (!cur_attr) {
372 continue;
373 }
374
375 if (cur_attr->plugin_descriptor != descriptor) {
376 continue;
377 }
378
379 switch (cur_attr->type) {
380 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT:
381 spec->init = cur_attr->value.init;
382 break;
383 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT:
384 spec->shared_lib_handle->exit = cur_attr->value.exit;
385 break;
386 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR:
387 bt_plugin_set_author(plugin, cur_attr->value.author);
388 break;
389 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE:
390 bt_plugin_set_license(plugin, cur_attr->value.license);
391 break;
392 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
393 bt_plugin_set_description(plugin, cur_attr->value.description);
394 break;
395 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION:
396 bt_plugin_set_version(plugin,
397 (unsigned int) cur_attr->value.version.major,
398 (unsigned int) cur_attr->value.version.minor,
399 (unsigned int) cur_attr->value.version.patch,
400 cur_attr->value.version.extra);
401 break;
402 default:
403 if (fail_on_load_error) {
404 BT_LIB_LOGW_APPEND_CAUSE(
405 "Unknown plugin descriptor attribute: "
406 "plugin-path=\"%s\", plugin-name=\"%s\", "
407 "attr-type-name=\"%s\", attr-type-id=%d",
408 spec->shared_lib_handle->path ?
409 spec->shared_lib_handle->path->str :
410 NULL,
411 descriptor->name, cur_attr->type_name,
412 cur_attr->type);
413 status = BT_FUNC_STATUS_ERROR;
414 goto end;
415 } else {
416 BT_LIB_LOGW(
417 "Ignoring unknown plugin descriptor attribute: "
418 "plugin-path=\"%s\", plugin-name=\"%s\", "
419 "attr-type-name=\"%s\", attr-type-id=%d",
420 spec->shared_lib_handle->path ?
421 spec->shared_lib_handle->path->str :
422 NULL,
423 descriptor->name, cur_attr->type_name,
424 cur_attr->type);
425 }
426
427 break;
428 }
429 }
430
431 /*
432 * Find component class descriptors attached to this plugin
433 * descriptor and initialize corresponding full component class
434 * descriptors in the array.
435 */
436 for (cur_cc_descr_ptr = cc_descriptors_begin; cur_cc_descr_ptr != cc_descriptors_end; cur_cc_descr_ptr++) {
437 const struct __bt_plugin_component_class_descriptor *cur_cc_descr =
438 *cur_cc_descr_ptr;
439 struct comp_class_full_descriptor full_descriptor = {0};
440
441 if (!cur_cc_descr) {
442 continue;
443 }
444
445 if (cur_cc_descr->plugin_descriptor != descriptor) {
446 continue;
447 }
448
449 full_descriptor.descriptor = cur_cc_descr;
450 g_array_append_val(comp_class_full_descriptors,
451 full_descriptor);
452 }
453
454 /*
455 * Find component class descriptor attributes attached to this
456 * plugin descriptor and update corresponding full component
457 * class descriptors in the array.
458 */
459 for (cur_cc_descr_attr_ptr = cc_descr_attrs_begin; cur_cc_descr_attr_ptr != cc_descr_attrs_end; cur_cc_descr_attr_ptr++) {
460 const struct __bt_plugin_component_class_descriptor_attribute *cur_cc_descr_attr =
461 *cur_cc_descr_attr_ptr;
462 enum bt_component_class_type cc_type;
463
464 if (!cur_cc_descr_attr) {
465 continue;
466 }
467
468 if (cur_cc_descr_attr->comp_class_descriptor->plugin_descriptor !=
469 descriptor) {
470 continue;
471 }
472
473 cc_type = cur_cc_descr_attr->comp_class_descriptor->type;
474
475 /* Find the corresponding component class descriptor entry */
476 for (i = 0; i < comp_class_full_descriptors->len; i++) {
477 struct comp_class_full_descriptor *cc_full_descr =
478 &g_array_index(comp_class_full_descriptors,
479 struct comp_class_full_descriptor, i);
480
481 if (cur_cc_descr_attr->comp_class_descriptor !=
482 cc_full_descr->descriptor) {
483 continue;
484 }
485
486 switch (cur_cc_descr_attr->type) {
487 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
488 cc_full_descr->description =
489 cur_cc_descr_attr->value.description;
490 break;
491 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP:
492 cc_full_descr->help =
493 cur_cc_descr_attr->value.help;
494 break;
495 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GET_SUPPORTED_MIP_VERSIONS_METHOD:
496 switch (cc_type) {
497 case BT_COMPONENT_CLASS_TYPE_SOURCE:
498 cc_full_descr->methods.source.get_supported_mip_versions =
499 cur_cc_descr_attr->value.source_get_supported_mip_versions_method;
500 break;
501 case BT_COMPONENT_CLASS_TYPE_FILTER:
502 cc_full_descr->methods.filter.get_supported_mip_versions =
503 cur_cc_descr_attr->value.filter_get_supported_mip_versions_method;
504 break;
505 case BT_COMPONENT_CLASS_TYPE_SINK:
506 cc_full_descr->methods.sink.get_supported_mip_versions =
507 cur_cc_descr_attr->value.sink_get_supported_mip_versions_method;
508 break;
509 default:
510 abort();
511 }
512 break;
513 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INITIALIZE_METHOD:
514 switch (cc_type) {
515 case BT_COMPONENT_CLASS_TYPE_SOURCE:
516 cc_full_descr->methods.source.init =
517 cur_cc_descr_attr->value.source_initialize_method;
518 break;
519 case BT_COMPONENT_CLASS_TYPE_FILTER:
520 cc_full_descr->methods.filter.init =
521 cur_cc_descr_attr->value.filter_initialize_method;
522 break;
523 case BT_COMPONENT_CLASS_TYPE_SINK:
524 cc_full_descr->methods.sink.init =
525 cur_cc_descr_attr->value.sink_initialize_method;
526 break;
527 default:
528 abort();
529 }
530 break;
531 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD:
532 switch (cc_type) {
533 case BT_COMPONENT_CLASS_TYPE_SOURCE:
534 cc_full_descr->methods.source.finalize =
535 cur_cc_descr_attr->value.source_finalize_method;
536 break;
537 case BT_COMPONENT_CLASS_TYPE_FILTER:
538 cc_full_descr->methods.filter.finalize =
539 cur_cc_descr_attr->value.filter_finalize_method;
540 break;
541 case BT_COMPONENT_CLASS_TYPE_SINK:
542 cc_full_descr->methods.sink.finalize =
543 cur_cc_descr_attr->value.sink_finalize_method;
544 break;
545 default:
546 abort();
547 }
548 break;
549 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD:
550 switch (cc_type) {
551 case BT_COMPONENT_CLASS_TYPE_SOURCE:
552 cc_full_descr->methods.source.query =
553 cur_cc_descr_attr->value.source_query_method;
554 break;
555 case BT_COMPONENT_CLASS_TYPE_FILTER:
556 cc_full_descr->methods.filter.query =
557 cur_cc_descr_attr->value.filter_query_method;
558 break;
559 case BT_COMPONENT_CLASS_TYPE_SINK:
560 cc_full_descr->methods.sink.query =
561 cur_cc_descr_attr->value.sink_query_method;
562 break;
563 default:
564 abort();
565 }
566 break;
567 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INPUT_PORT_CONNECTED_METHOD:
568 switch (cc_type) {
569 case BT_COMPONENT_CLASS_TYPE_FILTER:
570 cc_full_descr->methods.filter.input_port_connected =
571 cur_cc_descr_attr->value.filter_input_port_connected_method;
572 break;
573 case BT_COMPONENT_CLASS_TYPE_SINK:
574 cc_full_descr->methods.sink.input_port_connected =
575 cur_cc_descr_attr->value.sink_input_port_connected_method;
576 break;
577 default:
578 abort();
579 }
580 break;
581 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_OUTPUT_PORT_CONNECTED_METHOD:
582 switch (cc_type) {
583 case BT_COMPONENT_CLASS_TYPE_SOURCE:
584 cc_full_descr->methods.source.output_port_connected =
585 cur_cc_descr_attr->value.source_output_port_connected_method;
586 break;
587 case BT_COMPONENT_CLASS_TYPE_FILTER:
588 cc_full_descr->methods.filter.output_port_connected =
589 cur_cc_descr_attr->value.filter_output_port_connected_method;
590 break;
591 default:
592 abort();
593 }
594 break;
595 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_GRAPH_IS_CONFIGURED_METHOD:
596 switch (cc_type) {
597 case BT_COMPONENT_CLASS_TYPE_SINK:
598 cc_full_descr->methods.sink.graph_is_configured =
599 cur_cc_descr_attr->value.sink_graph_is_configured_method;
600 break;
601 default:
602 abort();
603 }
604 break;
605 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_INITIALIZE_METHOD:
606 switch (cc_type) {
607 case BT_COMPONENT_CLASS_TYPE_SOURCE:
608 cc_full_descr->methods.source.msg_iter_initialize =
609 cur_cc_descr_attr->value.source_msg_iter_initialize_method;
610 break;
611 case BT_COMPONENT_CLASS_TYPE_FILTER:
612 cc_full_descr->methods.filter.msg_iter_initialize =
613 cur_cc_descr_attr->value.filter_msg_iter_initialize_method;
614 break;
615 default:
616 abort();
617 }
618 break;
619 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_FINALIZE_METHOD:
620 switch (cc_type) {
621 case BT_COMPONENT_CLASS_TYPE_SOURCE:
622 cc_full_descr->methods.source.msg_iter_finalize =
623 cur_cc_descr_attr->value.source_msg_iter_finalize_method;
624 break;
625 case BT_COMPONENT_CLASS_TYPE_FILTER:
626 cc_full_descr->methods.filter.msg_iter_finalize =
627 cur_cc_descr_attr->value.filter_msg_iter_finalize_method;
628 break;
629 default:
630 abort();
631 }
632 break;
633 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_NS_FROM_ORIGIN_METHOD:
634 switch (cc_type) {
635 case BT_COMPONENT_CLASS_TYPE_SOURCE:
636 cc_full_descr->methods.source.msg_iter_seek_ns_from_origin =
637 cur_cc_descr_attr->value.source_msg_iter_seek_ns_from_origin_method;
638 break;
639 case BT_COMPONENT_CLASS_TYPE_FILTER:
640 cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin =
641 cur_cc_descr_attr->value.filter_msg_iter_seek_ns_from_origin_method;
642 break;
643 default:
644 abort();
645 }
646 break;
647 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_SEEK_BEGINNING_METHOD:
648 switch (cc_type) {
649 case BT_COMPONENT_CLASS_TYPE_SOURCE:
650 cc_full_descr->methods.source.msg_iter_seek_beginning =
651 cur_cc_descr_attr->value.source_msg_iter_seek_beginning_method;
652 break;
653 case BT_COMPONENT_CLASS_TYPE_FILTER:
654 cc_full_descr->methods.filter.msg_iter_seek_beginning =
655 cur_cc_descr_attr->value.filter_msg_iter_seek_beginning_method;
656 break;
657 default:
658 abort();
659 }
660 break;
661 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_NS_FROM_ORIGIN_METHOD:
662 switch (cc_type) {
663 case BT_COMPONENT_CLASS_TYPE_SOURCE:
664 cc_full_descr->methods.source.msg_iter_can_seek_ns_from_origin =
665 cur_cc_descr_attr->value.source_msg_iter_can_seek_ns_from_origin_method;
666 break;
667 case BT_COMPONENT_CLASS_TYPE_FILTER:
668 cc_full_descr->methods.filter.msg_iter_can_seek_ns_from_origin =
669 cur_cc_descr_attr->value.filter_msg_iter_can_seek_ns_from_origin_method;
670 break;
671 default:
672 abort();
673 }
674 break;
675 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_CAN_SEEK_BEGINNING_METHOD:
676 switch (cc_type) {
677 case BT_COMPONENT_CLASS_TYPE_SOURCE:
678 cc_full_descr->methods.source.msg_iter_can_seek_beginning =
679 cur_cc_descr_attr->value.source_msg_iter_can_seek_beginning_method;
680 break;
681 case BT_COMPONENT_CLASS_TYPE_FILTER:
682 cc_full_descr->methods.filter.msg_iter_can_seek_beginning =
683 cur_cc_descr_attr->value.filter_msg_iter_can_seek_beginning_method;
684 break;
685 default:
686 abort();
687 }
688 break;
689 default:
690 if (fail_on_load_error) {
691 BT_LIB_LOGW_APPEND_CAUSE(
692 "Unknown component class descriptor attribute: "
693 "plugin-path=\"%s\", "
694 "plugin-name=\"%s\", "
695 "comp-class-name=\"%s\", "
696 "comp-class-type=%s, "
697 "attr-type-name=\"%s\", "
698 "attr-type-id=%d",
699 spec->shared_lib_handle->path ?
700 spec->shared_lib_handle->path->str :
701 NULL,
702 descriptor->name,
703 cur_cc_descr_attr->comp_class_descriptor->name,
704 bt_component_class_type_string(
705 cur_cc_descr_attr->comp_class_descriptor->type),
706 cur_cc_descr_attr->type_name,
707 cur_cc_descr_attr->type);
708 status = BT_FUNC_STATUS_ERROR;
709 goto end;
710 } else {
711 BT_LIB_LOGW(
712 "Ignoring unknown component class descriptor attribute: "
713 "plugin-path=\"%s\", "
714 "plugin-name=\"%s\", "
715 "comp-class-name=\"%s\", "
716 "comp-class-type=%s, "
717 "attr-type-name=\"%s\", "
718 "attr-type-id=%d",
719 spec->shared_lib_handle->path ?
720 spec->shared_lib_handle->path->str :
721 NULL,
722 descriptor->name,
723 cur_cc_descr_attr->comp_class_descriptor->name,
724 bt_component_class_type_string(
725 cur_cc_descr_attr->comp_class_descriptor->type),
726 cur_cc_descr_attr->type_name,
727 cur_cc_descr_attr->type);
728 }
729
730 break;
731 }
732 }
733 }
734
735 /* Initialize plugin */
736 if (spec->init) {
737 enum bt_plugin_initialize_func_status init_status;
738
739 BT_LOGD_STR("Calling user's plugin initialization function.");
740 init_status = spec->init((void *) plugin);
741 BT_LOGD("User function returned: status=%s",
742 bt_common_func_status_string(init_status));
743
744 if (init_status < 0) {
745 if (fail_on_load_error) {
746 BT_LIB_LOGW_APPEND_CAUSE(
747 "User's plugin initialization function failed: "
748 "status=%s",
749 bt_common_func_status_string(init_status));
750 status = init_status;
751 goto end;
752 } else {
753 BT_LIB_LOGW(
754 "User's plugin initialization function failed: "
755 "status=%s",
756 bt_common_func_status_string(init_status));
757 status = BT_FUNC_STATUS_NOT_FOUND;
758 }
759
760 goto end;
761 }
762 }
763
764 spec->shared_lib_handle->init_called = BT_TRUE;
765
766 /* Add described component classes to plugin */
767 for (i = 0; i < comp_class_full_descriptors->len; i++) {
768 struct comp_class_full_descriptor *cc_full_descr =
769 &g_array_index(comp_class_full_descriptors,
770 struct comp_class_full_descriptor, i);
771 struct bt_component_class *comp_class = NULL;
772 struct bt_component_class_source *src_comp_class = NULL;
773 struct bt_component_class_filter *flt_comp_class = NULL;
774 struct bt_component_class_sink *sink_comp_class = NULL;
775
776 BT_LOGI("Creating and setting properties of plugin's component class: "
777 "plugin-path=\"%s\", plugin-name=\"%s\", "
778 "comp-class-name=\"%s\", comp-class-type=%s",
779 spec->shared_lib_handle->path ?
780 spec->shared_lib_handle->path->str :
781 NULL,
782 descriptor->name,
783 cc_full_descr->descriptor->name,
784 bt_component_class_type_string(
785 cc_full_descr->descriptor->type));
786
787 switch (cc_full_descr->descriptor->type) {
788 case BT_COMPONENT_CLASS_TYPE_SOURCE:
789 src_comp_class = bt_component_class_source_create(
790 cc_full_descr->descriptor->name,
791 cc_full_descr->descriptor->methods.source.msg_iter_next);
792 comp_class = bt_component_class_source_as_component_class(
793 src_comp_class);
794 break;
795 case BT_COMPONENT_CLASS_TYPE_FILTER:
796 flt_comp_class = bt_component_class_filter_create(
797 cc_full_descr->descriptor->name,
798 cc_full_descr->descriptor->methods.source.msg_iter_next);
799 comp_class = bt_component_class_filter_as_component_class(
800 flt_comp_class);
801 break;
802 case BT_COMPONENT_CLASS_TYPE_SINK:
803 sink_comp_class = bt_component_class_sink_create(
804 cc_full_descr->descriptor->name,
805 cc_full_descr->descriptor->methods.sink.consume);
806 comp_class = bt_component_class_sink_as_component_class(
807 sink_comp_class);
808 break;
809 default:
810 if (fail_on_load_error) {
811 BT_LIB_LOGW_APPEND_CAUSE(
812 "Unknown component class type: "
813 "plugin-path=\"%s\", plugin-name=\"%s\", "
814 "comp-class-name=\"%s\", comp-class-type=%d",
815 spec->shared_lib_handle->path->str ?
816 spec->shared_lib_handle->path->str :
817 NULL,
818 descriptor->name,
819 cc_full_descr->descriptor->name,
820 cc_full_descr->descriptor->type);
821 status = BT_FUNC_STATUS_ERROR;
822 goto end;
823 } else {
824 BT_LIB_LOGW(
825 "Ignoring unknown component class type: "
826 "plugin-path=\"%s\", plugin-name=\"%s\", "
827 "comp-class-name=\"%s\", comp-class-type=%d",
828 spec->shared_lib_handle->path->str ?
829 spec->shared_lib_handle->path->str :
830 NULL,
831 descriptor->name,
832 cc_full_descr->descriptor->name,
833 cc_full_descr->descriptor->type);
834 continue;
835 }
836 }
837
838 if (!comp_class) {
839 BT_LIB_LOGE_APPEND_CAUSE(
840 "Cannot create component class.");
841 status = BT_FUNC_STATUS_MEMORY_ERROR;
842 goto end;
843 }
844
845 if (cc_full_descr->description) {
846 ret = bt_component_class_set_description(
847 comp_class, cc_full_descr->description);
848 if (ret) {
849 BT_LIB_LOGE_APPEND_CAUSE(
850 "Cannot set component class's description.");
851 status = BT_FUNC_STATUS_MEMORY_ERROR;
852 BT_OBJECT_PUT_REF_AND_RESET(comp_class);
853 goto end;
854 }
855 }
856
857 if (cc_full_descr->help) {
858 ret = bt_component_class_set_help(comp_class,
859 cc_full_descr->help);
860 if (ret) {
861 BT_LIB_LOGE_APPEND_CAUSE(
862 "Cannot set component class's help string.");
863 status = BT_FUNC_STATUS_MEMORY_ERROR;
864 BT_OBJECT_PUT_REF_AND_RESET(comp_class);
865 goto end;
866 }
867 }
868
869 switch (cc_full_descr->descriptor->type) {
870 case BT_COMPONENT_CLASS_TYPE_SOURCE:
871 if (cc_full_descr->methods.source.get_supported_mip_versions) {
872 ret = bt_component_class_source_set_get_supported_mip_versions_method(
873 src_comp_class,
874 cc_full_descr->methods.source.get_supported_mip_versions);
875 if (ret) {
876 BT_LIB_LOGE_APPEND_CAUSE(
877 "Cannot set source component class's \"get supported MIP versions\" method.");
878 status = BT_FUNC_STATUS_MEMORY_ERROR;
879 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
880 goto end;
881 }
882 }
883
884 if (cc_full_descr->methods.source.init) {
885 ret = bt_component_class_source_set_initialize_method(
886 src_comp_class,
887 cc_full_descr->methods.source.init);
888 if (ret) {
889 BT_LIB_LOGE_APPEND_CAUSE(
890 "Cannot set source component class's initialization method.");
891 status = BT_FUNC_STATUS_MEMORY_ERROR;
892 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
893 goto end;
894 }
895 }
896
897 if (cc_full_descr->methods.source.finalize) {
898 ret = bt_component_class_source_set_finalize_method(
899 src_comp_class,
900 cc_full_descr->methods.source.finalize);
901 if (ret) {
902 BT_LIB_LOGE_APPEND_CAUSE(
903 "Cannot set source component class's finalization method.");
904 status = BT_FUNC_STATUS_MEMORY_ERROR;
905 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
906 goto end;
907 }
908 }
909
910 if (cc_full_descr->methods.source.query) {
911 ret = bt_component_class_source_set_query_method(
912 src_comp_class,
913 cc_full_descr->methods.source.query);
914 if (ret) {
915 BT_LIB_LOGE_APPEND_CAUSE(
916 "Cannot set source component class's query method.");
917 status = BT_FUNC_STATUS_MEMORY_ERROR;
918 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
919 goto end;
920 }
921 }
922
923 if (cc_full_descr->methods.source.output_port_connected) {
924 ret = bt_component_class_source_set_output_port_connected_method(
925 src_comp_class,
926 cc_full_descr->methods.source.output_port_connected);
927 if (ret) {
928 BT_LIB_LOGE_APPEND_CAUSE(
929 "Cannot set source component class's \"output port connected\" method.");
930 status = BT_FUNC_STATUS_MEMORY_ERROR;
931 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
932 goto end;
933 }
934 }
935
936 if (cc_full_descr->methods.source.msg_iter_initialize) {
937 ret = bt_component_class_source_set_message_iterator_initialize_method(
938 src_comp_class,
939 cc_full_descr->methods.source.msg_iter_initialize);
940 if (ret) {
941 BT_LIB_LOGE_APPEND_CAUSE(
942 "Cannot set source component class's message iterator initialization method.");
943 status = BT_FUNC_STATUS_MEMORY_ERROR;
944 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
945 goto end;
946 }
947 }
948
949 if (cc_full_descr->methods.source.msg_iter_finalize) {
950 ret = bt_component_class_source_set_message_iterator_finalize_method(
951 src_comp_class,
952 cc_full_descr->methods.source.msg_iter_finalize);
953 if (ret) {
954 BT_LIB_LOGE_APPEND_CAUSE(
955 "Cannot set source component class's message iterator finalization method.");
956 status = BT_FUNC_STATUS_MEMORY_ERROR;
957 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
958 goto end;
959 }
960 }
961
962 if (cc_full_descr->methods.source.msg_iter_seek_ns_from_origin) {
963 ret = bt_component_class_source_set_message_iterator_seek_ns_from_origin_methods(
964 src_comp_class,
965 cc_full_descr->methods.source.msg_iter_seek_ns_from_origin,
966 cc_full_descr->methods.source.msg_iter_can_seek_ns_from_origin);
967 if (ret) {
968 BT_LIB_LOGE_APPEND_CAUSE(
969 "Cannot set source component class's message iterator \"seek nanoseconds from origin\" methods.");
970 status = BT_FUNC_STATUS_MEMORY_ERROR;
971 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
972 goto end;
973 }
974 }
975
976 if (cc_full_descr->methods.source.msg_iter_seek_beginning) {
977 ret = bt_component_class_source_set_message_iterator_seek_beginning_methods(
978 src_comp_class,
979 cc_full_descr->methods.source.msg_iter_seek_beginning,
980 cc_full_descr->methods.source.msg_iter_can_seek_beginning);
981 if (ret) {
982 BT_LIB_LOGE_APPEND_CAUSE(
983 "Cannot set source component class's message iterator \"seek beginning\" methods.");
984 status = BT_FUNC_STATUS_MEMORY_ERROR;
985 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
986 goto end;
987 }
988 }
989
990 break;
991 case BT_COMPONENT_CLASS_TYPE_FILTER:
992 if (cc_full_descr->methods.filter.get_supported_mip_versions) {
993 ret = bt_component_class_filter_set_get_supported_mip_versions_method(
994 flt_comp_class,
995 cc_full_descr->methods.filter.get_supported_mip_versions);
996 if (ret) {
997 BT_LIB_LOGE_APPEND_CAUSE(
998 "Cannot set filter component class's \"get supported MIP versions\" method.");
999 status = BT_FUNC_STATUS_MEMORY_ERROR;
1000 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1001 goto end;
1002 }
1003 }
1004
1005 if (cc_full_descr->methods.filter.init) {
1006 ret = bt_component_class_filter_set_initialize_method(
1007 flt_comp_class,
1008 cc_full_descr->methods.filter.init);
1009 if (ret) {
1010 BT_LIB_LOGE_APPEND_CAUSE(
1011 "Cannot set filter component class's initialization method.");
1012 status = BT_FUNC_STATUS_MEMORY_ERROR;
1013 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1014 goto end;
1015 }
1016 }
1017
1018 if (cc_full_descr->methods.filter.finalize) {
1019 ret = bt_component_class_filter_set_finalize_method(
1020 flt_comp_class,
1021 cc_full_descr->methods.filter.finalize);
1022 if (ret) {
1023 BT_LIB_LOGE_APPEND_CAUSE(
1024 "Cannot set filter component class's finalization method.");
1025 status = BT_FUNC_STATUS_MEMORY_ERROR;
1026 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1027 goto end;
1028 }
1029 }
1030
1031 if (cc_full_descr->methods.filter.query) {
1032 ret = bt_component_class_filter_set_query_method(
1033 flt_comp_class,
1034 cc_full_descr->methods.filter.query);
1035 if (ret) {
1036 BT_LIB_LOGE_APPEND_CAUSE(
1037 "Cannot set filter component class's query method.");
1038 status = BT_FUNC_STATUS_MEMORY_ERROR;
1039 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1040 goto end;
1041 }
1042 }
1043
1044 if (cc_full_descr->methods.filter.input_port_connected) {
1045 ret = bt_component_class_filter_set_input_port_connected_method(
1046 flt_comp_class,
1047 cc_full_descr->methods.filter.input_port_connected);
1048 if (ret) {
1049 BT_LIB_LOGE_APPEND_CAUSE(
1050 "Cannot set filter component class's \"input port connected\" method.");
1051 status = BT_FUNC_STATUS_MEMORY_ERROR;
1052 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1053 goto end;
1054 }
1055 }
1056
1057 if (cc_full_descr->methods.filter.output_port_connected) {
1058 ret = bt_component_class_filter_set_output_port_connected_method(
1059 flt_comp_class,
1060 cc_full_descr->methods.filter.output_port_connected);
1061 if (ret) {
1062 BT_LIB_LOGE_APPEND_CAUSE(
1063 "Cannot set filter component class's \"output port connected\" method.");
1064 status = BT_FUNC_STATUS_MEMORY_ERROR;
1065 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1066 goto end;
1067 }
1068 }
1069
1070 if (cc_full_descr->methods.filter.msg_iter_initialize) {
1071 ret = bt_component_class_filter_set_message_iterator_initialize_method(
1072 flt_comp_class,
1073 cc_full_descr->methods.filter.msg_iter_initialize);
1074 if (ret) {
1075 BT_LIB_LOGE_APPEND_CAUSE(
1076 "Cannot set filter component class's message iterator initialization method.");
1077 status = BT_FUNC_STATUS_MEMORY_ERROR;
1078 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1079 goto end;
1080 }
1081 }
1082
1083 if (cc_full_descr->methods.filter.msg_iter_finalize) {
1084 ret = bt_component_class_filter_set_message_iterator_finalize_method(
1085 flt_comp_class,
1086 cc_full_descr->methods.filter.msg_iter_finalize);
1087 if (ret) {
1088 BT_LIB_LOGE_APPEND_CAUSE(
1089 "Cannot set filter component class's message iterator finalization method.");
1090 status = BT_FUNC_STATUS_MEMORY_ERROR;
1091 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1092 goto end;
1093 }
1094 }
1095
1096 if (cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin) {
1097 ret = bt_component_class_filter_set_message_iterator_seek_ns_from_origin_methods(
1098 flt_comp_class,
1099 cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin,
1100 cc_full_descr->methods.filter.msg_iter_can_seek_ns_from_origin);
1101 if (ret) {
1102 BT_LIB_LOGE_APPEND_CAUSE(
1103 "Cannot set filter component class's message iterator \"seek nanoseconds from origin\" methods.");
1104 status = BT_FUNC_STATUS_MEMORY_ERROR;
1105 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1106 goto end;
1107 }
1108 }
1109
1110 if (cc_full_descr->methods.filter.msg_iter_seek_beginning) {
1111 ret = bt_component_class_filter_set_message_iterator_seek_beginning_methods(
1112 flt_comp_class,
1113 cc_full_descr->methods.filter.msg_iter_seek_beginning,
1114 cc_full_descr->methods.filter.msg_iter_can_seek_beginning);
1115 if (ret) {
1116 BT_LIB_LOGE_APPEND_CAUSE(
1117 "Cannot set filter component class's message iterator \"seek beginning\" methods.");
1118 status = BT_FUNC_STATUS_MEMORY_ERROR;
1119 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1120 goto end;
1121 }
1122 }
1123
1124 break;
1125 case BT_COMPONENT_CLASS_TYPE_SINK:
1126 if (cc_full_descr->methods.sink.get_supported_mip_versions) {
1127 ret = bt_component_class_sink_set_get_supported_mip_versions_method(
1128 sink_comp_class,
1129 cc_full_descr->methods.sink.get_supported_mip_versions);
1130 if (ret) {
1131 BT_LIB_LOGE_APPEND_CAUSE(
1132 "Cannot set sink component class's \"get supported MIP versions\" method.");
1133 status = BT_FUNC_STATUS_MEMORY_ERROR;
1134 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1135 goto end;
1136 }
1137 }
1138
1139 if (cc_full_descr->methods.sink.init) {
1140 ret = bt_component_class_sink_set_initialize_method(
1141 sink_comp_class,
1142 cc_full_descr->methods.sink.init);
1143 if (ret) {
1144 BT_LIB_LOGE_APPEND_CAUSE(
1145 "Cannot set sink component class's initialization method.");
1146 status = BT_FUNC_STATUS_MEMORY_ERROR;
1147 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1148 goto end;
1149 }
1150 }
1151
1152 if (cc_full_descr->methods.sink.finalize) {
1153 ret = bt_component_class_sink_set_finalize_method(
1154 sink_comp_class,
1155 cc_full_descr->methods.sink.finalize);
1156 if (ret) {
1157 BT_LIB_LOGE_APPEND_CAUSE(
1158 "Cannot set sink component class's finalization method.");
1159 status = BT_FUNC_STATUS_MEMORY_ERROR;
1160 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1161 goto end;
1162 }
1163 }
1164
1165 if (cc_full_descr->methods.sink.query) {
1166 ret = bt_component_class_sink_set_query_method(
1167 sink_comp_class,
1168 cc_full_descr->methods.sink.query);
1169 if (ret) {
1170 BT_LIB_LOGE_APPEND_CAUSE(
1171 "Cannot set sink component class's query method.");
1172 status = BT_FUNC_STATUS_MEMORY_ERROR;
1173 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1174 goto end;
1175 }
1176 }
1177
1178 if (cc_full_descr->methods.sink.input_port_connected) {
1179 ret = bt_component_class_sink_set_input_port_connected_method(
1180 sink_comp_class,
1181 cc_full_descr->methods.sink.input_port_connected);
1182 if (ret) {
1183 BT_LIB_LOGE_APPEND_CAUSE(
1184 "Cannot set sink component class's \"input port connected\" method.");
1185 status = BT_FUNC_STATUS_MEMORY_ERROR;
1186 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1187 goto end;
1188 }
1189 }
1190
1191 if (cc_full_descr->methods.sink.graph_is_configured) {
1192 ret = bt_component_class_sink_set_graph_is_configured_method(
1193 sink_comp_class,
1194 cc_full_descr->methods.sink.graph_is_configured);
1195 if (ret) {
1196 BT_LIB_LOGE_APPEND_CAUSE(
1197 "Cannot set sink component class's \"graph is configured\" method.");
1198 status = BT_FUNC_STATUS_MEMORY_ERROR;
1199 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1200 goto end;
1201 }
1202 }
1203
1204 break;
1205 default:
1206 abort();
1207 }
1208
1209 /*
1210 * Add component class to the plugin object.
1211 *
1212 * This will call back
1213 * bt_plugin_so_on_add_component_class() so that we can
1214 * add a mapping in the component class list when we
1215 * know the component class is successfully added.
1216 */
1217 status = bt_plugin_add_component_class(plugin,
1218 (void *) comp_class);
1219 BT_OBJECT_PUT_REF_AND_RESET(comp_class);
1220 if (status < 0) {
1221 BT_LIB_LOGE_APPEND_CAUSE(
1222 "Cannot add component class to plugin.");
1223 goto end;
1224 }
1225 }
1226
1227 end:
1228 g_array_free(comp_class_full_descriptors, TRUE);
1229 return status;
1230 }
1231
1232 static
1233 struct bt_plugin *bt_plugin_so_create_empty(
1234 struct bt_plugin_so_shared_lib_handle *shared_lib_handle)
1235 {
1236 struct bt_plugin *plugin;
1237 struct bt_plugin_so_spec_data *spec;
1238
1239 plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_SO);
1240 if (!plugin) {
1241 goto error;
1242 }
1243
1244 plugin->destroy_spec_data = bt_plugin_so_destroy_spec_data;
1245 plugin->spec_data = g_new0(struct bt_plugin_so_spec_data, 1);
1246 if (!plugin->spec_data) {
1247 BT_LIB_LOGE_APPEND_CAUSE(
1248 "Failed to allocate one SO plugin specific data structure.");
1249 goto error;
1250 }
1251
1252 spec = plugin->spec_data;
1253 spec->shared_lib_handle = shared_lib_handle;
1254 bt_object_get_ref_no_null_check(spec->shared_lib_handle);
1255 goto end;
1256
1257 error:
1258 BT_OBJECT_PUT_REF_AND_RESET(plugin);
1259
1260 end:
1261 return plugin;
1262 }
1263
1264 static
1265 size_t count_non_null_items_in_section(const void *begin, const void *end)
1266 {
1267 size_t count = 0;
1268 const int * const *begin_int = (const int * const *) begin;
1269 const int * const *end_int = (const int * const *) end;
1270 const int * const *iter;
1271
1272 for (iter = begin_int; iter != end_int; iter++) {
1273 if (*iter) {
1274 count++;
1275 }
1276 }
1277
1278 return count;
1279 }
1280
1281 static
1282 int bt_plugin_so_create_all_from_sections(
1283 struct bt_plugin_so_shared_lib_handle *shared_lib_handle,
1284 bool fail_on_load_error,
1285 struct __bt_plugin_descriptor const * const *descriptors_begin,
1286 struct __bt_plugin_descriptor const * const *descriptors_end,
1287 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
1288 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
1289 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
1290 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
1291 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
1292 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end,
1293 struct bt_plugin_set **plugin_set_out)
1294 {
1295 int status = BT_FUNC_STATUS_OK;
1296 size_t descriptor_count;
1297 size_t attrs_count;
1298 size_t cc_descriptors_count;
1299 size_t cc_descr_attrs_count;
1300 size_t i;
1301
1302 BT_ASSERT(shared_lib_handle);
1303 BT_ASSERT(plugin_set_out);
1304 *plugin_set_out = NULL;
1305 descriptor_count = count_non_null_items_in_section(descriptors_begin, descriptors_end);
1306 attrs_count = count_non_null_items_in_section(attrs_begin, attrs_end);
1307 cc_descriptors_count = count_non_null_items_in_section(cc_descriptors_begin, cc_descriptors_end);
1308 cc_descr_attrs_count = count_non_null_items_in_section(cc_descr_attrs_begin, cc_descr_attrs_end);
1309 BT_LOGI("Creating all SO plugins from sections: "
1310 "plugin-path=\"%s\", "
1311 "descr-begin-addr=%p, descr-end-addr=%p, "
1312 "attrs-begin-addr=%p, attrs-end-addr=%p, "
1313 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
1314 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p, "
1315 "descr-count=%zu, attrs-count=%zu, "
1316 "cc-descr-count=%zu, cc-descr-attrs-count=%zu",
1317 shared_lib_handle->path ? shared_lib_handle->path->str : NULL,
1318 descriptors_begin, descriptors_end,
1319 attrs_begin, attrs_end,
1320 cc_descriptors_begin, cc_descriptors_end,
1321 cc_descr_attrs_begin, cc_descr_attrs_end,
1322 descriptor_count, attrs_count,
1323 cc_descriptors_count, cc_descr_attrs_count);
1324 *plugin_set_out = bt_plugin_set_create();
1325 if (!*plugin_set_out) {
1326 BT_LIB_LOGE_APPEND_CAUSE("Cannot create empty plugin set.");
1327 status = BT_FUNC_STATUS_MEMORY_ERROR;
1328 goto error;
1329 }
1330
1331 for (i = 0; i < descriptors_end - descriptors_begin; i++) {
1332 const struct __bt_plugin_descriptor *descriptor =
1333 descriptors_begin[i];
1334 struct bt_plugin *plugin;
1335
1336 if (!descriptor) {
1337 continue;
1338 }
1339
1340 BT_LOGI("Creating plugin object for plugin: name=\"%s\"",
1341 descriptor->name);
1342 plugin = bt_plugin_so_create_empty(shared_lib_handle);
1343 if (!plugin) {
1344 BT_LIB_LOGE_APPEND_CAUSE(
1345 "Cannot create empty shared library handle.");
1346 status = BT_FUNC_STATUS_MEMORY_ERROR;
1347 goto error;
1348 }
1349
1350 if (shared_lib_handle->path) {
1351 bt_plugin_set_path(plugin,
1352 shared_lib_handle->path->str);
1353 }
1354
1355 status = bt_plugin_so_init(plugin, fail_on_load_error,
1356 descriptor, attrs_begin, attrs_end,
1357 cc_descriptors_begin, cc_descriptors_end,
1358 cc_descr_attrs_begin, cc_descr_attrs_end);
1359 if (status == BT_FUNC_STATUS_OK) {
1360 /* Add to plugin set */
1361 bt_plugin_set_add_plugin(*plugin_set_out, plugin);
1362 BT_OBJECT_PUT_REF_AND_RESET(plugin);
1363 } else if (status < 0) {
1364 /*
1365 * bt_plugin_so_init() handles
1366 * `fail_on_load_error`, so this is a "real"
1367 * error.
1368 */
1369 BT_LIB_LOGW_APPEND_CAUSE(
1370 "Cannot initialize SO plugin object from sections.");
1371 BT_OBJECT_PUT_REF_AND_RESET(plugin);
1372 goto error;
1373 }
1374
1375 BT_ASSERT(!plugin);
1376 }
1377
1378 BT_ASSERT(*plugin_set_out);
1379
1380 if ((*plugin_set_out)->plugins->len == 0) {
1381 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out);
1382 status = BT_FUNC_STATUS_NOT_FOUND;
1383 }
1384
1385 goto end;
1386
1387 error:
1388 BT_ASSERT(status < 0);
1389 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out);
1390
1391 end:
1392 return status;
1393 }
1394
1395 BT_HIDDEN
1396 int bt_plugin_so_create_all_from_static(bool fail_on_load_error,
1397 struct bt_plugin_set **plugin_set_out)
1398 {
1399 int status;
1400 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
1401
1402 BT_ASSERT(plugin_set_out);
1403 *plugin_set_out = NULL;
1404 status = bt_plugin_so_shared_lib_handle_create(NULL,
1405 &shared_lib_handle);
1406 if (status != BT_FUNC_STATUS_OK) {
1407 BT_ASSERT(!shared_lib_handle);
1408 goto end;
1409 }
1410
1411 BT_ASSERT(shared_lib_handle);
1412 BT_LOGD_STR("Creating all SO plugins from built-in plugins.");
1413 status = bt_plugin_so_create_all_from_sections(shared_lib_handle,
1414 fail_on_load_error,
1415 __bt_get_begin_section_plugin_descriptors(),
1416 __bt_get_end_section_plugin_descriptors(),
1417 __bt_get_begin_section_plugin_descriptor_attributes(),
1418 __bt_get_end_section_plugin_descriptor_attributes(),
1419 __bt_get_begin_section_component_class_descriptors(),
1420 __bt_get_end_section_component_class_descriptors(),
1421 __bt_get_begin_section_component_class_descriptor_attributes(),
1422 __bt_get_end_section_component_class_descriptor_attributes(),
1423 plugin_set_out);
1424 BT_ASSERT((status == BT_FUNC_STATUS_OK && *plugin_set_out &&
1425 (*plugin_set_out)->plugins->len > 0) || !*plugin_set_out);
1426
1427 end:
1428 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle);
1429 return status;
1430 }
1431
1432 BT_HIDDEN
1433 int bt_plugin_so_create_all_from_file(const char *path,
1434 bool fail_on_load_error, struct bt_plugin_set **plugin_set_out)
1435 {
1436 size_t path_len;
1437 int status;
1438 struct __bt_plugin_descriptor const * const *descriptors_begin = NULL;
1439 struct __bt_plugin_descriptor const * const *descriptors_end = NULL;
1440 struct __bt_plugin_descriptor_attribute const * const *attrs_begin = NULL;
1441 struct __bt_plugin_descriptor_attribute const * const *attrs_end = NULL;
1442 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin = NULL;
1443 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end = NULL;
1444 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin = NULL;
1445 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end = NULL;
1446 struct __bt_plugin_descriptor const * const *(*get_begin_section_plugin_descriptors)(void);
1447 struct __bt_plugin_descriptor const * const *(*get_end_section_plugin_descriptors)(void);
1448 struct __bt_plugin_descriptor_attribute const * const *(*get_begin_section_plugin_descriptor_attributes)(void);
1449 struct __bt_plugin_descriptor_attribute const * const *(*get_end_section_plugin_descriptor_attributes)(void);
1450 struct __bt_plugin_component_class_descriptor const * const *(*get_begin_section_component_class_descriptors)(void);
1451 struct __bt_plugin_component_class_descriptor const * const *(*get_end_section_component_class_descriptors)(void);
1452 struct __bt_plugin_component_class_descriptor_attribute const * const *(*get_begin_section_component_class_descriptor_attributes)(void);
1453 struct __bt_plugin_component_class_descriptor_attribute const * const *(*get_end_section_component_class_descriptor_attributes)(void);
1454 bt_bool is_libtool_wrapper = BT_FALSE, is_shared_object = BT_FALSE;
1455 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
1456
1457 BT_ASSERT(path);
1458 BT_ASSERT(plugin_set_out);
1459 *plugin_set_out = NULL;
1460 path_len = strlen(path);
1461
1462 /*
1463 * An SO plugin file must have a known plugin file suffix. So the file
1464 * path must be longer than the suffix length.
1465 */
1466 if (path_len <= PLUGIN_SUFFIX_LEN) {
1467 BT_LOGI("Path is too short to be an `.so` or `.la` plugin file:"
1468 "path=%s, path-length=%zu, min-length=%zu",
1469 path, path_len, PLUGIN_SUFFIX_LEN);
1470 status = BT_FUNC_STATUS_NOT_FOUND;
1471 goto end;
1472 }
1473
1474 BT_LOGI("Trying to create all SO plugins from file: path=\"%s\"", path);
1475 path_len++;
1476
1477 /*
1478 * Check if the file ends with a known plugin file type suffix
1479 * (i.e. .so or .la on Linux).
1480 */
1481 is_libtool_wrapper = !strncmp(LIBTOOL_PLUGIN_SUFFIX,
1482 path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN,
1483 LIBTOOL_PLUGIN_SUFFIX_LEN);
1484 is_shared_object = !strncmp(NATIVE_PLUGIN_SUFFIX,
1485 path + path_len - NATIVE_PLUGIN_SUFFIX_LEN,
1486 NATIVE_PLUGIN_SUFFIX_LEN);
1487 if (!is_shared_object && !is_libtool_wrapper) {
1488 /* Name indicates this is not a plugin file; not an error */
1489 BT_LOGI("File is not an SO plugin file: path=\"%s\"", path);
1490 status = BT_FUNC_STATUS_NOT_FOUND;
1491 goto end;
1492 }
1493
1494 status = bt_plugin_so_shared_lib_handle_create(path,
1495 &shared_lib_handle);
1496 if (status != BT_FUNC_STATUS_OK) {
1497 /* bt_plugin_so_shared_lib_handle_create() logs more details */
1498 BT_ASSERT(!shared_lib_handle);
1499 goto end;
1500 }
1501
1502 if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_plugin_descriptors",
1503 (gpointer *) &get_begin_section_plugin_descriptors)) {
1504 descriptors_begin = get_begin_section_plugin_descriptors();
1505 } else {
1506 /*
1507 * Use this first symbol to know whether or not this
1508 * shared object _looks like_ a Babeltrace plugin. Since
1509 * g_module_symbol() failed, assume that this is not a
1510 * Babeltrace plugin, so it's not an error.
1511 */
1512 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1513 "symbol=\"%s\"", path,
1514 "__bt_get_begin_section_plugin_descriptors");
1515 status = BT_FUNC_STATUS_NOT_FOUND;
1516 goto end;
1517 }
1518
1519 /*
1520 * If g_module_symbol() fails for any of the other symbols, fail
1521 * if `fail_on_load_error` is true.
1522 */
1523 if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_plugin_descriptors",
1524 (gpointer *) &get_end_section_plugin_descriptors)) {
1525 descriptors_end = get_end_section_plugin_descriptors();
1526 } else {
1527 if (fail_on_load_error) {
1528 BT_LIB_LOGW_APPEND_CAUSE(
1529 "Cannot resolve plugin symbol: path=\"%s\", "
1530 "symbol=\"%s\"", path,
1531 "__bt_get_end_section_plugin_descriptors");
1532 status = BT_FUNC_STATUS_ERROR;
1533 } else {
1534 BT_LIB_LOGW(
1535 "Cannot resolve plugin symbol: path=\"%s\", "
1536 "symbol=\"%s\"", path,
1537 "__bt_get_end_section_plugin_descriptors");
1538 status = BT_FUNC_STATUS_NOT_FOUND;
1539 }
1540
1541 goto end;
1542 }
1543
1544 if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_plugin_descriptor_attributes",
1545 (gpointer *) &get_begin_section_plugin_descriptor_attributes)) {
1546 attrs_begin = get_begin_section_plugin_descriptor_attributes();
1547 } else {
1548 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1549 "symbol=\"%s\"", path,
1550 "__bt_get_begin_section_plugin_descriptor_attributes");
1551 }
1552
1553 if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_plugin_descriptor_attributes",
1554 (gpointer *) &get_end_section_plugin_descriptor_attributes)) {
1555 attrs_end = get_end_section_plugin_descriptor_attributes();
1556 } else {
1557 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1558 "symbol=\"%s\"", path,
1559 "__bt_get_end_section_plugin_descriptor_attributes");
1560 }
1561
1562 if ((!!attrs_begin - !!attrs_end) != 0) {
1563 if (fail_on_load_error) {
1564 BT_LIB_LOGW_APPEND_CAUSE(
1565 "Found section start or end symbol, but not both: "
1566 "path=\"%s\", symbol-start=\"%s\", "
1567 "symbol-end=\"%s\", symbol-start-addr=%p, "
1568 "symbol-end-addr=%p",
1569 path, "__bt_get_begin_section_plugin_descriptor_attributes",
1570 "__bt_get_end_section_plugin_descriptor_attributes",
1571 attrs_begin, attrs_end);
1572 status = BT_FUNC_STATUS_ERROR;
1573 } else {
1574 BT_LIB_LOGW(
1575 "Found section start or end symbol, but not both: "
1576 "path=\"%s\", symbol-start=\"%s\", "
1577 "symbol-end=\"%s\", symbol-start-addr=%p, "
1578 "symbol-end-addr=%p",
1579 path, "__bt_get_begin_section_plugin_descriptor_attributes",
1580 "__bt_get_end_section_plugin_descriptor_attributes",
1581 attrs_begin, attrs_end);
1582 status = BT_FUNC_STATUS_NOT_FOUND;
1583 }
1584
1585 goto end;
1586 }
1587
1588 if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_component_class_descriptors",
1589 (gpointer *) &get_begin_section_component_class_descriptors)) {
1590 cc_descriptors_begin = get_begin_section_component_class_descriptors();
1591 } else {
1592 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1593 "symbol=\"%s\"", path,
1594 "__bt_get_begin_section_component_class_descriptors");
1595 }
1596
1597 if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_component_class_descriptors",
1598 (gpointer *) &get_end_section_component_class_descriptors)) {
1599 cc_descriptors_end = get_end_section_component_class_descriptors();
1600 } else {
1601 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1602 "symbol=\"%s\"", path,
1603 "__bt_get_end_section_component_class_descriptors");
1604 }
1605
1606 if ((!!cc_descriptors_begin - !!cc_descriptors_end) != 0) {
1607 if (fail_on_load_error) {
1608 BT_LIB_LOGW_APPEND_CAUSE(
1609 "Found section start or end symbol, but not both: "
1610 "path=\"%s\", symbol-start=\"%s\", "
1611 "symbol-end=\"%s\", symbol-start-addr=%p, "
1612 "symbol-end-addr=%p",
1613 path, "__bt_get_begin_section_component_class_descriptors",
1614 "__bt_get_end_section_component_class_descriptors",
1615 cc_descriptors_begin, cc_descriptors_end);
1616 status = BT_FUNC_STATUS_ERROR;
1617 } else {
1618 BT_LIB_LOGW(
1619 "Found section start or end symbol, but not both: "
1620 "path=\"%s\", symbol-start=\"%s\", "
1621 "symbol-end=\"%s\", symbol-start-addr=%p, "
1622 "symbol-end-addr=%p",
1623 path, "__bt_get_begin_section_component_class_descriptors",
1624 "__bt_get_end_section_component_class_descriptors",
1625 cc_descriptors_begin, cc_descriptors_end);
1626 status = BT_FUNC_STATUS_NOT_FOUND;
1627 }
1628
1629 goto end;
1630 }
1631
1632 if (g_module_symbol(shared_lib_handle->module, "__bt_get_begin_section_component_class_descriptor_attributes",
1633 (gpointer *) &get_begin_section_component_class_descriptor_attributes)) {
1634 cc_descr_attrs_begin = get_begin_section_component_class_descriptor_attributes();
1635 } else {
1636 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1637 "symbol=\"%s\"", path,
1638 "__bt_get_begin_section_component_class_descriptor_attributes");
1639 }
1640
1641 if (g_module_symbol(shared_lib_handle->module, "__bt_get_end_section_component_class_descriptor_attributes",
1642 (gpointer *) &get_end_section_component_class_descriptor_attributes)) {
1643 cc_descr_attrs_end = get_end_section_component_class_descriptor_attributes();
1644 } else {
1645 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
1646 "symbol=\"%s\"", path,
1647 "__bt_get_end_section_component_class_descriptor_attributes");
1648 }
1649
1650 if ((!!cc_descr_attrs_begin - !!cc_descr_attrs_end) != 0) {
1651 if (fail_on_load_error) {
1652 BT_LIB_LOGW_APPEND_CAUSE(
1653 "Found section start or end symbol, but not both: "
1654 "path=\"%s\", symbol-start=\"%s\", "
1655 "symbol-end=\"%s\", symbol-start-addr=%p, "
1656 "symbol-end-addr=%p",
1657 path, "__bt_get_begin_section_component_class_descriptor_attributes",
1658 "__bt_get_end_section_component_class_descriptor_attributes",
1659 cc_descr_attrs_begin, cc_descr_attrs_end);
1660 status = BT_FUNC_STATUS_ERROR;
1661 } else {
1662 BT_LIB_LOGW(
1663 "Found section start or end symbol, but not both: "
1664 "path=\"%s\", symbol-start=\"%s\", "
1665 "symbol-end=\"%s\", symbol-start-addr=%p, "
1666 "symbol-end-addr=%p",
1667 path, "__bt_get_begin_section_component_class_descriptor_attributes",
1668 "__bt_get_end_section_component_class_descriptor_attributes",
1669 cc_descr_attrs_begin, cc_descr_attrs_end);
1670 status = BT_FUNC_STATUS_NOT_FOUND;
1671 }
1672
1673 goto end;
1674 }
1675
1676 /* Initialize plugin */
1677 BT_LOGD_STR("Initializing plugin object.");
1678 status = bt_plugin_so_create_all_from_sections(shared_lib_handle,
1679 fail_on_load_error,
1680 descriptors_begin, descriptors_end, attrs_begin, attrs_end,
1681 cc_descriptors_begin, cc_descriptors_end,
1682 cc_descr_attrs_begin, cc_descr_attrs_end, plugin_set_out);
1683
1684 end:
1685 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle);
1686 return status;
1687 }
1688
1689 static
1690 void plugin_comp_class_destroy_listener(struct bt_component_class *comp_class,
1691 void *data)
1692 {
1693 bt_list_del(&comp_class->node);
1694 BT_OBJECT_PUT_REF_AND_RESET(comp_class->so_handle);
1695 BT_LOGD("Component class destroyed: removed entry from list: "
1696 "comp-cls-addr=%p", comp_class);
1697 }
1698
1699 void bt_plugin_so_on_add_component_class(struct bt_plugin *plugin,
1700 struct bt_component_class *comp_class)
1701 {
1702 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
1703
1704 BT_ASSERT(plugin->spec_data);
1705 BT_ASSERT(plugin->type == BT_PLUGIN_TYPE_SO);
1706
1707 bt_list_add(&comp_class->node, &component_class_list);
1708 comp_class->so_handle = spec->shared_lib_handle;
1709 bt_object_get_ref_no_null_check(comp_class->so_handle);
1710
1711 /* Add our custom destroy listener */
1712 bt_component_class_add_destroy_listener(comp_class,
1713 plugin_comp_class_destroy_listener, NULL);
1714 }
This page took 0.124321 seconds and 4 git commands to generate.