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