Cleanup: add `#include <stdbool.h>` whenever `bool` type is used
[babeltrace.git] / src / lib / plugin / plugin-so.c
CommitLineData
55bb57e0 1/*
e2f7325d 2 * Copyright 2017-2018 Philippe Proulx <pproulx@efficios.com>
55bb57e0 3 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
55bb57e0
PP
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
350ad6c1 26#define BT_LOG_TAG "LIB/PLUGIN-SO"
c2d9d9cf 27#include "lib/logging.h"
3fe0bf43 28
578e048b
MJ
29#include "common/assert.h"
30#include "lib/assert-pre.h"
31#include "compat/compiler.h"
3fadfbc0 32#include <babeltrace2/plugin/plugin-dev.h>
578e048b 33#include "lib/graph/component-class.h"
3fadfbc0
MJ
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>
578e048b 39#include "common/list.h"
55bb57e0 40#include <string.h>
c4f23e30 41#include <stdbool.h>
0fbb9a9f 42#include <stdlib.h>
55bb57e0
PP
43#include <glib.h>
44#include <gmodule.h>
45
578e048b
MJ
46#include "plugin.h"
47#include "plugin-so.h"
d24d5663
PP
48#include "lib/func-status.h"
49#include "common/common.h"
578e048b 50
44a3451a 51#define NATIVE_PLUGIN_SUFFIX "." G_MODULE_SUFFIX
55bb57e0
PP
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
91d81473 56#define PLUGIN_SUFFIX_LEN bt_max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
55bb57e0
PP
57 sizeof(LIBTOOL_PLUGIN_SUFFIX))
58
52238017 59BT_PLUGIN_MODULE();
55bb57e0
PP
60
61/*
bfa9a4be
MD
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.
55bb57e0 66 *
bfa9a4be 67 * The list items are the component classes created with
55bb57e0
PP
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 *
bfa9a4be 73 * [component] --ref-> [component class]-> [shlib handle]
55bb57e0 74 *
bfa9a4be 75 * It allows this use-case:
55bb57e0 76 *
c8db3219 77 * my_plugins = bt_plugin_find_all_from_file("/path/to/my-plugin.so");
55bb57e0
PP
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 *
bfa9a4be
MD
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.
55bb57e0 90 */
bfa9a4be 91
55bb57e0 92static
bfa9a4be 93BT_LIST_HEAD(component_class_list);
55bb57e0
PP
94
95__attribute__((destructor)) static
bfa9a4be
MD
96void 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);
65300d60 102 BT_OBJECT_PUT_REF_AND_RESET(comp_class->so_handle);
55bb57e0 103 }
d94d92ac 104
bfa9a4be 105 BT_LOGD_STR("Released references from all component classes to shared library handles.");
55bb57e0
PP
106}
107
108static
109void bt_plugin_so_shared_lib_handle_destroy(struct bt_object *obj)
110{
111 struct bt_plugin_so_shared_lib_handle *shared_lib_handle;
112
f6ccaed9 113 BT_ASSERT(obj);
55bb57e0
PP
114 shared_lib_handle = container_of(obj,
115 struct bt_plugin_so_shared_lib_handle, base);
3fe0bf43
PP
116 const char *path = shared_lib_handle->path ?
117 shared_lib_handle->path->str : NULL;
118
3f7d4d90 119 BT_LOGI("Destroying shared library handle: addr=%p, path=\"%s\"",
3fe0bf43 120 shared_lib_handle, path);
55bb57e0
PP
121
122 if (shared_lib_handle->init_called && shared_lib_handle->exit) {
3fe0bf43 123 BT_LOGD_STR("Calling user's plugin exit function.");
9724cce9
PP
124 shared_lib_handle->exit();
125 BT_LOGD_STR("User function returned.");
55bb57e0
PP
126 }
127
128 if (shared_lib_handle->module) {
21e6ffa5 129#ifdef BT_DEBUG_MODE
f1447220
PP
130 /*
131 * Valgrind shows incomplete stack traces when
132 * dynamically loaded libraries are closed before it
16b7b5e7 133 * finishes. Use the LIBBABELTRACE2_NO_DLCLOSE in a debug
f1447220
PP
134 * build to avoid this.
135 */
16b7b5e7 136 const char *var = getenv("LIBBABELTRACE2_NO_DLCLOSE");
f1447220
PP
137
138 if (!var || strcmp(var, "1") != 0) {
139#endif
3f7d4d90 140 BT_LOGI("Closing GModule: path=\"%s\"", path);
3fe0bf43 141
f1447220 142 if (!g_module_close(shared_lib_handle->module)) {
870631a2
PP
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 */
3fe0bf43
PP
148 BT_LOGE("Cannot close GModule: %s: path=\"%s\"",
149 g_module_error(), path);
f1447220 150 }
db5504f9
PP
151
152 shared_lib_handle->module = NULL;
21e6ffa5 153#ifdef BT_DEBUG_MODE
3fe0bf43 154 } else {
16b7b5e7 155 BT_LOGI("Not closing GModule because `LIBBABELTRACE2_NO_DLCLOSE=1`: "
3fe0bf43 156 "path=\"%s\"", path);
55bb57e0 157 }
f1447220 158#endif
55bb57e0
PP
159 }
160
161 if (shared_lib_handle->path) {
162 g_string_free(shared_lib_handle->path, TRUE);
db5504f9 163 shared_lib_handle->path = NULL;
55bb57e0
PP
164 }
165
166 g_free(shared_lib_handle);
167}
168
169static
d24d5663 170int bt_plugin_so_shared_lib_handle_create(
9736d991
PP
171 const char *path,
172 struct bt_plugin_so_shared_lib_handle **shared_lib_handle)
55bb57e0 173{
d24d5663 174 int status = BT_FUNC_STATUS_OK;
55bb57e0 175
9736d991 176 BT_ASSERT(shared_lib_handle);
3f7d4d90 177 BT_LOGI("Creating shared library handle: path=\"%s\"", path);
9736d991
PP
178 *shared_lib_handle = g_new0(struct bt_plugin_so_shared_lib_handle, 1);
179 if (!*shared_lib_handle) {
870631a2 180 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate one shared library handle.");
d24d5663 181 status = BT_FUNC_STATUS_MEMORY_ERROR;
9736d991 182 goto end;
55bb57e0
PP
183 }
184
9736d991 185 bt_object_init_shared(&(*shared_lib_handle)->base,
3fea54f6 186 bt_plugin_so_shared_lib_handle_destroy);
55bb57e0
PP
187
188 if (!path) {
189 goto end;
190 }
191
9736d991
PP
192 (*shared_lib_handle)->path = g_string_new(path);
193 if (!(*shared_lib_handle)->path) {
870631a2 194 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GString.");
d24d5663 195 status = BT_FUNC_STATUS_MEMORY_ERROR;
9736d991 196 goto end;
55bb57e0
PP
197 }
198
9736d991
PP
199 (*shared_lib_handle)->module = g_module_open(path, G_MODULE_BIND_LOCAL);
200 if (!(*shared_lib_handle)->module) {
50ad9320 201 /*
3f7d4d90 202 * INFO-level logging because we're only _trying_ to
50ad9320
PP
203 * open this file as a Babeltrace plugin: if it's not,
204 * it's not an error. And because this can be tried
3f7d4d90
PP
205 * during bt_plugin_find_all_from_dir(), it's not even a
206 * warning.
50ad9320 207 */
3f7d4d90 208 BT_LOGI("Cannot open GModule: %s: path=\"%s\"",
3fe0bf43 209 g_module_error(), path);
9736d991 210 BT_OBJECT_PUT_REF_AND_RESET(*shared_lib_handle);
d24d5663 211 status = BT_FUNC_STATUS_NOT_FOUND;
9736d991 212 goto end;
55bb57e0
PP
213 }
214
215 goto end;
216
55bb57e0 217end:
d24d5663 218 BT_ASSERT(*shared_lib_handle || status != BT_FUNC_STATUS_OK);
9736d991 219 if (*shared_lib_handle) {
3f7d4d90 220 BT_LOGI("Created shared library handle: path=\"%s\", addr=%p",
9736d991 221 path, *shared_lib_handle);
3fe0bf43
PP
222 }
223
9736d991 224 return status;
55bb57e0
PP
225}
226
6fbd4105 227static
55bb57e0
PP
228void 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
f6ccaed9
PP
236 BT_ASSERT(plugin->type == BT_PLUGIN_TYPE_SO);
237 BT_ASSERT(spec);
65300d60 238 BT_OBJECT_PUT_REF_AND_RESET(spec->shared_lib_handle);
55bb57e0
PP
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 */
270static
d24d5663 271int bt_plugin_so_init(struct bt_plugin *plugin,
9736d991 272 bool fail_on_load_error,
55bb57e0
PP
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;
279b3f15 288 const char *help;
d94d92ac
PP
289
290 union {
291 struct {
2b55df78 292 bt_component_class_source_get_supported_mip_versions_method get_supported_mip_versions;
21a9f056 293 bt_component_class_source_initialize_method init;
0d72b8c3
PP
294 bt_component_class_source_finalize_method finalize;
295 bt_component_class_source_query_method query;
0d72b8c3 296 bt_component_class_source_output_port_connected_method output_port_connected;
21a9f056 297 bt_component_class_source_message_iterator_initialize_method msg_iter_initialize;
d6e69534 298 bt_component_class_source_message_iterator_finalize_method msg_iter_finalize;
7474e7d3
PP
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;
d94d92ac
PP
303 } source;
304
305 struct {
2b55df78 306 bt_component_class_filter_get_supported_mip_versions_method get_supported_mip_versions;
21a9f056 307 bt_component_class_filter_initialize_method init;
0d72b8c3
PP
308 bt_component_class_filter_finalize_method finalize;
309 bt_component_class_filter_query_method query;
0d72b8c3
PP
310 bt_component_class_filter_input_port_connected_method input_port_connected;
311 bt_component_class_filter_output_port_connected_method output_port_connected;
21a9f056 312 bt_component_class_filter_message_iterator_initialize_method msg_iter_initialize;
d6e69534 313 bt_component_class_filter_message_iterator_finalize_method msg_iter_finalize;
7474e7d3
PP
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;
d94d92ac
PP
318 } filter;
319
320 struct {
2b55df78 321 bt_component_class_sink_get_supported_mip_versions_method get_supported_mip_versions;
21a9f056 322 bt_component_class_sink_initialize_method init;
0d72b8c3
PP
323 bt_component_class_sink_finalize_method finalize;
324 bt_component_class_sink_query_method query;
0d72b8c3 325 bt_component_class_sink_input_port_connected_method input_port_connected;
5badd463 326 bt_component_class_sink_graph_is_configured_method graph_is_configured;
d94d92ac
PP
327 } sink;
328 } methods;
55bb57e0
PP
329 };
330
d24d5663 331 int status = BT_FUNC_STATUS_OK;
55bb57e0
PP
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
3f7d4d90 340 BT_LOGI("Initializing plugin object from descriptors found in sections: "
3fe0bf43
PP
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);
55bb57e0
PP
351 comp_class_full_descriptors = g_array_new(FALSE, TRUE,
352 sizeof(struct comp_class_full_descriptor));
353 if (!comp_class_full_descriptors) {
870631a2 354 BT_LIB_LOGE_APPEND_CAUSE("Failed to allocate a GArray.");
d24d5663 355 status = BT_FUNC_STATUS_MEMORY_ERROR;
55bb57e0
PP
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
5084732e 371 if (!cur_attr) {
52238017
MJ
372 continue;
373 }
374
55bb57e0
PP
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:
9736d991 403 if (fail_on_load_error) {
870631a2
PP
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);
b189a968 413 status = BT_FUNC_STATUS_ERROR;
9736d991 414 goto end;
870631a2 415 } else {
a0cdfce8 416 BT_LIB_LOGW(
870631a2
PP
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);
9736d991
PP
425 }
426
55bb57e0
PP
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
5084732e 441 if (!cur_cc_descr) {
52238017
MJ
442 continue;
443 }
444
55bb57e0
PP
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;
d94d92ac 462 enum bt_component_class_type cc_type;
55bb57e0 463
5084732e 464 if (!cur_cc_descr_attr) {
52238017
MJ
465 continue;
466 }
467
55bb57e0
PP
468 if (cur_cc_descr_attr->comp_class_descriptor->plugin_descriptor !=
469 descriptor) {
470 continue;
471 }
472
d94d92ac
PP
473 cc_type = cur_cc_descr_attr->comp_class_descriptor->type;
474
55bb57e0
PP
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
d94d92ac 481 if (cur_cc_descr_attr->comp_class_descriptor !=
55bb57e0 482 cc_full_descr->descriptor) {
d94d92ac
PP
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;
2b55df78
PP
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;
21a9f056 513 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INITIALIZE_METHOD:
d94d92ac
PP
514 switch (cc_type) {
515 case BT_COMPONENT_CLASS_TYPE_SOURCE:
516 cc_full_descr->methods.source.init =
21a9f056 517 cur_cc_descr_attr->value.source_initialize_method;
55bb57e0 518 break;
d94d92ac
PP
519 case BT_COMPONENT_CLASS_TYPE_FILTER:
520 cc_full_descr->methods.filter.init =
21a9f056 521 cur_cc_descr_attr->value.filter_initialize_method;
279b3f15 522 break;
d94d92ac
PP
523 case BT_COMPONENT_CLASS_TYPE_SINK:
524 cc_full_descr->methods.sink.init =
21a9f056 525 cur_cc_descr_attr->value.sink_initialize_method;
55bb57e0 526 break;
d94d92ac
PP
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;
55bb57e0 536 break;
d94d92ac
PP
537 case BT_COMPONENT_CLASS_TYPE_FILTER:
538 cc_full_descr->methods.filter.finalize =
539 cur_cc_descr_attr->value.filter_finalize_method;
8463eac2 540 break;
d94d92ac
PP
541 case BT_COMPONENT_CLASS_TYPE_SINK:
542 cc_full_descr->methods.sink.finalize =
543 cur_cc_descr_attr->value.sink_finalize_method;
72b913fb 544 break;
d94d92ac
PP
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;
0d8b4d8e 554 break;
d94d92ac
PP
555 case BT_COMPONENT_CLASS_TYPE_FILTER:
556 cc_full_descr->methods.filter.query =
557 cur_cc_descr_attr->value.filter_query_method;
55bb57e0 558 break;
d94d92ac
PP
559 case BT_COMPONENT_CLASS_TYPE_SINK:
560 cc_full_descr->methods.sink.query =
561 cur_cc_descr_attr->value.sink_query_method;
55bb57e0 562 break;
d94d92ac
PP
563 default:
564 abort();
565 }
566 break;
d94d92ac
PP
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;
55bb57e0 576 break;
55bb57e0 577 default:
d94d92ac
PP
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;
55bb57e0 590 break;
d94d92ac
PP
591 default:
592 abort();
55bb57e0 593 }
d94d92ac 594 break;
5badd463
PP
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;
21a9f056 605 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_INITIALIZE_METHOD:
d94d92ac
PP
606 switch (cc_type) {
607 case BT_COMPONENT_CLASS_TYPE_SOURCE:
21a9f056
FD
608 cc_full_descr->methods.source.msg_iter_initialize =
609 cur_cc_descr_attr->value.source_msg_iter_initialize_method;
d94d92ac
PP
610 break;
611 case BT_COMPONENT_CLASS_TYPE_FILTER:
21a9f056
FD
612 cc_full_descr->methods.filter.msg_iter_initialize =
613 cur_cc_descr_attr->value.filter_msg_iter_initialize_method;
d94d92ac
PP
614 break;
615 default:
616 abort();
617 }
618 break;
d6e69534 619 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_MSG_ITER_FINALIZE_METHOD:
d94d92ac
PP
620 switch (cc_type) {
621 case BT_COMPONENT_CLASS_TYPE_SOURCE:
d6e69534
PP
622 cc_full_descr->methods.source.msg_iter_finalize =
623 cur_cc_descr_attr->value.source_msg_iter_finalize_method;
d94d92ac
PP
624 break;
625 case BT_COMPONENT_CLASS_TYPE_FILTER:
d6e69534
PP
626 cc_full_descr->methods.filter.msg_iter_finalize =
627 cur_cc_descr_attr->value.filter_msg_iter_finalize_method;
d94d92ac
PP
628 break;
629 default:
630 abort();
631 }
632 break;
7474e7d3
PP
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;
d94d92ac 689 default:
9736d991 690 if (fail_on_load_error) {
870631a2
PP
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);
b189a968 708 status = BT_FUNC_STATUS_ERROR;
9736d991 709 goto end;
870631a2 710 } else {
a0cdfce8 711 BT_LIB_LOGW(
870631a2
PP
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);
9736d991
PP
728 }
729
d94d92ac 730 break;
55bb57e0
PP
731 }
732 }
733 }
734
735 /* Initialize plugin */
736 if (spec->init) {
21a9f056 737 enum bt_plugin_initialize_func_status init_status;
a21d1cb8 738
3fe0bf43 739 BT_LOGD_STR("Calling user's plugin initialization function.");
a21d1cb8 740 init_status = spec->init((void *) plugin);
9736d991 741 BT_LOGD("User function returned: status=%s",
d24d5663 742 bt_common_func_status_string(init_status));
3fe0bf43 743
9724cce9 744 if (init_status < 0) {
9736d991 745 if (fail_on_load_error) {
870631a2
PP
746 BT_LIB_LOGW_APPEND_CAUSE(
747 "User's plugin initialization function failed: "
748 "status=%s",
749 bt_common_func_status_string(init_status));
d24d5663 750 status = init_status;
9736d991 751 goto end;
870631a2 752 } else {
a0cdfce8 753 BT_LIB_LOGW(
870631a2
PP
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;
9736d991 758 }
870631a2
PP
759
760 goto end;
55bb57e0
PP
761 }
762 }
763
c55a9f58 764 spec->shared_lib_handle->init_called = BT_TRUE;
55bb57e0
PP
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);
0d72b8c3
PP
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;
55bb57e0 775
3f7d4d90 776 BT_LOGI("Creating and setting properties of plugin's component class: "
3fe0bf43
PP
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
55bb57e0
PP
787 switch (cc_full_descr->descriptor->type) {
788 case BT_COMPONENT_CLASS_TYPE_SOURCE:
0d72b8c3 789 src_comp_class = bt_component_class_source_create(
55bb57e0 790 cc_full_descr->descriptor->name,
d6e69534 791 cc_full_descr->descriptor->methods.source.msg_iter_next);
0d72b8c3 792 comp_class = bt_component_class_source_as_component_class(
d94d92ac 793 src_comp_class);
55bb57e0
PP
794 break;
795 case BT_COMPONENT_CLASS_TYPE_FILTER:
0d72b8c3 796 flt_comp_class = bt_component_class_filter_create(
55bb57e0 797 cc_full_descr->descriptor->name,
d6e69534 798 cc_full_descr->descriptor->methods.source.msg_iter_next);
0d72b8c3 799 comp_class = bt_component_class_filter_as_component_class(
d94d92ac 800 flt_comp_class);
55bb57e0
PP
801 break;
802 case BT_COMPONENT_CLASS_TYPE_SINK:
0d72b8c3 803 sink_comp_class = bt_component_class_sink_create(
55bb57e0
PP
804 cc_full_descr->descriptor->name,
805 cc_full_descr->descriptor->methods.sink.consume);
0d72b8c3 806 comp_class = bt_component_class_sink_as_component_class(
d94d92ac 807 sink_comp_class);
55bb57e0
PP
808 break;
809 default:
9736d991 810 if (fail_on_load_error) {
870631a2
PP
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);
b189a968 821 status = BT_FUNC_STATUS_ERROR;
9736d991 822 goto end;
870631a2 823 } else {
a0cdfce8 824 BT_LIB_LOGW(
870631a2
PP
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;
9736d991 835 }
55bb57e0
PP
836 }
837
838 if (!comp_class) {
870631a2
PP
839 BT_LIB_LOGE_APPEND_CAUSE(
840 "Cannot create component class.");
d24d5663 841 status = BT_FUNC_STATUS_MEMORY_ERROR;
55bb57e0
PP
842 goto end;
843 }
844
845 if (cc_full_descr->description) {
0d72b8c3 846 ret = bt_component_class_set_description(
d94d92ac 847 comp_class, cc_full_descr->description);
55bb57e0 848 if (ret) {
870631a2
PP
849 BT_LIB_LOGE_APPEND_CAUSE(
850 "Cannot set component class's description.");
d24d5663 851 status = BT_FUNC_STATUS_MEMORY_ERROR;
65300d60 852 BT_OBJECT_PUT_REF_AND_RESET(comp_class);
55bb57e0
PP
853 goto end;
854 }
855 }
856
279b3f15 857 if (cc_full_descr->help) {
0d72b8c3 858 ret = bt_component_class_set_help(comp_class,
279b3f15
PP
859 cc_full_descr->help);
860 if (ret) {
870631a2
PP
861 BT_LIB_LOGE_APPEND_CAUSE(
862 "Cannot set component class's help string.");
d24d5663 863 status = BT_FUNC_STATUS_MEMORY_ERROR;
65300d60 864 BT_OBJECT_PUT_REF_AND_RESET(comp_class);
279b3f15
PP
865 goto end;
866 }
867 }
868
d94d92ac
PP
869 switch (cc_full_descr->descriptor->type) {
870 case BT_COMPONENT_CLASS_TYPE_SOURCE:
2b55df78
PP
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
d94d92ac 884 if (cc_full_descr->methods.source.init) {
21a9f056 885 ret = bt_component_class_source_set_initialize_method(
d94d92ac
PP
886 src_comp_class,
887 cc_full_descr->methods.source.init);
888 if (ret) {
870631a2
PP
889 BT_LIB_LOGE_APPEND_CAUSE(
890 "Cannot set source component class's initialization method.");
d24d5663 891 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
892 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
893 goto end;
894 }
55bb57e0 895 }
55bb57e0 896
d94d92ac 897 if (cc_full_descr->methods.source.finalize) {
0d72b8c3 898 ret = bt_component_class_source_set_finalize_method(
d94d92ac
PP
899 src_comp_class,
900 cc_full_descr->methods.source.finalize);
901 if (ret) {
870631a2
PP
902 BT_LIB_LOGE_APPEND_CAUSE(
903 "Cannot set source component class's finalization method.");
d24d5663 904 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
905 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
906 goto end;
907 }
55bb57e0 908 }
55bb57e0 909
d94d92ac 910 if (cc_full_descr->methods.source.query) {
0d72b8c3 911 ret = bt_component_class_source_set_query_method(
d94d92ac
PP
912 src_comp_class,
913 cc_full_descr->methods.source.query);
914 if (ret) {
870631a2
PP
915 BT_LIB_LOGE_APPEND_CAUSE(
916 "Cannot set source component class's query method.");
d24d5663 917 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
918 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
919 goto end;
920 }
8463eac2 921 }
8463eac2 922
d94d92ac 923 if (cc_full_descr->methods.source.output_port_connected) {
0d72b8c3 924 ret = bt_component_class_source_set_output_port_connected_method(
d94d92ac
PP
925 src_comp_class,
926 cc_full_descr->methods.source.output_port_connected);
927 if (ret) {
870631a2
PP
928 BT_LIB_LOGE_APPEND_CAUSE(
929 "Cannot set source component class's \"output port connected\" method.");
d24d5663 930 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
931 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
932 goto end;
933 }
0d8b4d8e 934 }
0d8b4d8e 935
21a9f056
FD
936 if (cc_full_descr->methods.source.msg_iter_initialize) {
937 ret = bt_component_class_source_set_message_iterator_initialize_method(
d94d92ac 938 src_comp_class,
21a9f056 939 cc_full_descr->methods.source.msg_iter_initialize);
55bb57e0 940 if (ret) {
870631a2
PP
941 BT_LIB_LOGE_APPEND_CAUSE(
942 "Cannot set source component class's message iterator initialization method.");
d24d5663 943 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac 944 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
55bb57e0
PP
945 goto end;
946 }
947 }
948
d6e69534
PP
949 if (cc_full_descr->methods.source.msg_iter_finalize) {
950 ret = bt_component_class_source_set_message_iterator_finalize_method(
d94d92ac 951 src_comp_class,
d6e69534 952 cc_full_descr->methods.source.msg_iter_finalize);
55bb57e0 953 if (ret) {
870631a2
PP
954 BT_LIB_LOGE_APPEND_CAUSE(
955 "Cannot set source component class's message iterator finalization method.");
d24d5663 956 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac 957 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
55bb57e0
PP
958 goto end;
959 }
960 }
d94d92ac 961
7474e7d3 962 if (cc_full_descr->methods.source.msg_iter_seek_ns_from_origin) {
2e1b5615 963 ret = bt_component_class_source_set_message_iterator_seek_ns_from_origin_methods(
7474e7d3 964 src_comp_class,
2e1b5615 965 cc_full_descr->methods.source.msg_iter_seek_ns_from_origin,
7474e7d3
PP
966 cc_full_descr->methods.source.msg_iter_can_seek_ns_from_origin);
967 if (ret) {
870631a2 968 BT_LIB_LOGE_APPEND_CAUSE(
2e1b5615 969 "Cannot set source component class's message iterator \"seek nanoseconds from origin\" methods.");
d24d5663 970 status = BT_FUNC_STATUS_MEMORY_ERROR;
7474e7d3
PP
971 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
972 goto end;
973 }
974 }
975
2e1b5615
SM
976 if (cc_full_descr->methods.source.msg_iter_seek_beginning) {
977 ret = bt_component_class_source_set_message_iterator_seek_beginning_methods(
7474e7d3 978 src_comp_class,
2e1b5615 979 cc_full_descr->methods.source.msg_iter_seek_beginning,
7474e7d3
PP
980 cc_full_descr->methods.source.msg_iter_can_seek_beginning);
981 if (ret) {
870631a2 982 BT_LIB_LOGE_APPEND_CAUSE(
2e1b5615 983 "Cannot set source component class's message iterator \"seek beginning\" methods.");
d24d5663 984 status = BT_FUNC_STATUS_MEMORY_ERROR;
7474e7d3
PP
985 BT_OBJECT_PUT_REF_AND_RESET(src_comp_class);
986 goto end;
987 }
988 }
989
55bb57e0
PP
990 break;
991 case BT_COMPONENT_CLASS_TYPE_FILTER:
2b55df78
PP
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
d94d92ac 1005 if (cc_full_descr->methods.filter.init) {
21a9f056 1006 ret = bt_component_class_filter_set_initialize_method(
d94d92ac
PP
1007 flt_comp_class,
1008 cc_full_descr->methods.filter.init);
1009 if (ret) {
870631a2
PP
1010 BT_LIB_LOGE_APPEND_CAUSE(
1011 "Cannot set filter component class's initialization method.");
d24d5663 1012 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
1013 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1014 goto end;
1015 }
1016 }
1017
1018 if (cc_full_descr->methods.filter.finalize) {
0d72b8c3 1019 ret = bt_component_class_filter_set_finalize_method(
d94d92ac
PP
1020 flt_comp_class,
1021 cc_full_descr->methods.filter.finalize);
1022 if (ret) {
870631a2
PP
1023 BT_LIB_LOGE_APPEND_CAUSE(
1024 "Cannot set filter component class's finalization method.");
d24d5663 1025 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
1026 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1027 goto end;
1028 }
1029 }
1030
1031 if (cc_full_descr->methods.filter.query) {
0d72b8c3 1032 ret = bt_component_class_filter_set_query_method(
d94d92ac
PP
1033 flt_comp_class,
1034 cc_full_descr->methods.filter.query);
1035 if (ret) {
870631a2
PP
1036 BT_LIB_LOGE_APPEND_CAUSE(
1037 "Cannot set filter component class's query method.");
d24d5663 1038 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
1039 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1040 goto end;
1041 }
1042 }
1043
d94d92ac 1044 if (cc_full_descr->methods.filter.input_port_connected) {
0d72b8c3 1045 ret = bt_component_class_filter_set_input_port_connected_method(
d94d92ac
PP
1046 flt_comp_class,
1047 cc_full_descr->methods.filter.input_port_connected);
1048 if (ret) {
870631a2
PP
1049 BT_LIB_LOGE_APPEND_CAUSE(
1050 "Cannot set filter component class's \"input port connected\" method.");
d24d5663 1051 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
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) {
0d72b8c3 1058 ret = bt_component_class_filter_set_output_port_connected_method(
d94d92ac
PP
1059 flt_comp_class,
1060 cc_full_descr->methods.filter.output_port_connected);
1061 if (ret) {
870631a2
PP
1062 BT_LIB_LOGE_APPEND_CAUSE(
1063 "Cannot set filter component class's \"output port connected\" method.");
d24d5663 1064 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
1065 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1066 goto end;
1067 }
1068 }
1069
21a9f056
FD
1070 if (cc_full_descr->methods.filter.msg_iter_initialize) {
1071 ret = bt_component_class_filter_set_message_iterator_initialize_method(
d94d92ac 1072 flt_comp_class,
21a9f056 1073 cc_full_descr->methods.filter.msg_iter_initialize);
55bb57e0 1074 if (ret) {
870631a2
PP
1075 BT_LIB_LOGE_APPEND_CAUSE(
1076 "Cannot set filter component class's message iterator initialization method.");
d24d5663 1077 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac 1078 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
55bb57e0
PP
1079 goto end;
1080 }
1081 }
1082
d6e69534
PP
1083 if (cc_full_descr->methods.filter.msg_iter_finalize) {
1084 ret = bt_component_class_filter_set_message_iterator_finalize_method(
d94d92ac 1085 flt_comp_class,
d6e69534 1086 cc_full_descr->methods.filter.msg_iter_finalize);
55bb57e0 1087 if (ret) {
870631a2
PP
1088 BT_LIB_LOGE_APPEND_CAUSE(
1089 "Cannot set filter component class's message iterator finalization method.");
d24d5663 1090 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac 1091 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
55bb57e0
PP
1092 goto end;
1093 }
1094 }
d94d92ac 1095
7474e7d3 1096 if (cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin) {
2e1b5615 1097 ret = bt_component_class_filter_set_message_iterator_seek_ns_from_origin_methods(
7474e7d3 1098 flt_comp_class,
2e1b5615 1099 cc_full_descr->methods.filter.msg_iter_seek_ns_from_origin,
7474e7d3
PP
1100 cc_full_descr->methods.filter.msg_iter_can_seek_ns_from_origin);
1101 if (ret) {
870631a2 1102 BT_LIB_LOGE_APPEND_CAUSE(
2e1b5615 1103 "Cannot set filter component class's message iterator \"seek nanoseconds from origin\" methods.");
d24d5663 1104 status = BT_FUNC_STATUS_MEMORY_ERROR;
7474e7d3
PP
1105 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1106 goto end;
1107 }
1108 }
1109
2e1b5615
SM
1110 if (cc_full_descr->methods.filter.msg_iter_seek_beginning) {
1111 ret = bt_component_class_filter_set_message_iterator_seek_beginning_methods(
7474e7d3 1112 flt_comp_class,
2e1b5615 1113 cc_full_descr->methods.filter.msg_iter_seek_beginning,
7474e7d3
PP
1114 cc_full_descr->methods.filter.msg_iter_can_seek_beginning);
1115 if (ret) {
870631a2 1116 BT_LIB_LOGE_APPEND_CAUSE(
2e1b5615 1117 "Cannot set filter component class's message iterator \"seek beginning\" methods.");
d24d5663 1118 status = BT_FUNC_STATUS_MEMORY_ERROR;
7474e7d3
PP
1119 BT_OBJECT_PUT_REF_AND_RESET(flt_comp_class);
1120 goto end;
1121 }
1122 }
1123
55bb57e0
PP
1124 break;
1125 case BT_COMPONENT_CLASS_TYPE_SINK:
2b55df78
PP
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
d94d92ac 1139 if (cc_full_descr->methods.sink.init) {
21a9f056 1140 ret = bt_component_class_sink_set_initialize_method(
d94d92ac
PP
1141 sink_comp_class,
1142 cc_full_descr->methods.sink.init);
1143 if (ret) {
870631a2
PP
1144 BT_LIB_LOGE_APPEND_CAUSE(
1145 "Cannot set sink component class's initialization method.");
d24d5663 1146 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
1147 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1148 goto end;
1149 }
1150 }
1151
1152 if (cc_full_descr->methods.sink.finalize) {
0d72b8c3 1153 ret = bt_component_class_sink_set_finalize_method(
d94d92ac
PP
1154 sink_comp_class,
1155 cc_full_descr->methods.sink.finalize);
1156 if (ret) {
870631a2
PP
1157 BT_LIB_LOGE_APPEND_CAUSE(
1158 "Cannot set sink component class's finalization method.");
d24d5663 1159 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
1160 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1161 goto end;
1162 }
1163 }
1164
1165 if (cc_full_descr->methods.sink.query) {
0d72b8c3 1166 ret = bt_component_class_sink_set_query_method(
d94d92ac
PP
1167 sink_comp_class,
1168 cc_full_descr->methods.sink.query);
1169 if (ret) {
870631a2
PP
1170 BT_LIB_LOGE_APPEND_CAUSE(
1171 "Cannot set sink component class's query method.");
d24d5663 1172 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
1173 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1174 goto end;
1175 }
1176 }
1177
d94d92ac 1178 if (cc_full_descr->methods.sink.input_port_connected) {
0d72b8c3 1179 ret = bt_component_class_sink_set_input_port_connected_method(
d94d92ac
PP
1180 sink_comp_class,
1181 cc_full_descr->methods.sink.input_port_connected);
1182 if (ret) {
870631a2
PP
1183 BT_LIB_LOGE_APPEND_CAUSE(
1184 "Cannot set sink component class's \"input port connected\" method.");
d24d5663 1185 status = BT_FUNC_STATUS_MEMORY_ERROR;
d94d92ac
PP
1186 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1187 goto end;
1188 }
1189 }
1190
5badd463
PP
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) {
870631a2
PP
1196 BT_LIB_LOGE_APPEND_CAUSE(
1197 "Cannot set sink component class's \"graph is configured\" method.");
d24d5663 1198 status = BT_FUNC_STATUS_MEMORY_ERROR;
5badd463
PP
1199 BT_OBJECT_PUT_REF_AND_RESET(sink_comp_class);
1200 goto end;
1201 }
1202 }
1203
55bb57e0
PP
1204 break;
1205 default:
0fbb9a9f 1206 abort();
55bb57e0
PP
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
d94d92ac
PP
1214 * add a mapping in the component class list when we
1215 * know the component class is successfully added.
55bb57e0
PP
1216 */
1217 status = bt_plugin_add_component_class(plugin,
d94d92ac 1218 (void *) comp_class);
65300d60 1219 BT_OBJECT_PUT_REF_AND_RESET(comp_class);
55bb57e0 1220 if (status < 0) {
870631a2
PP
1221 BT_LIB_LOGE_APPEND_CAUSE(
1222 "Cannot add component class to plugin.");
55bb57e0
PP
1223 goto end;
1224 }
1225 }
1226
55bb57e0
PP
1227end:
1228 g_array_free(comp_class_full_descriptors, TRUE);
1229 return status;
1230}
1231
1232static
1233struct 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
6fbd4105 1244 plugin->destroy_spec_data = bt_plugin_so_destroy_spec_data;
55bb57e0
PP
1245 plugin->spec_data = g_new0(struct bt_plugin_so_spec_data, 1);
1246 if (!plugin->spec_data) {
870631a2
PP
1247 BT_LIB_LOGE_APPEND_CAUSE(
1248 "Failed to allocate one SO plugin specific data structure.");
55bb57e0
PP
1249 goto error;
1250 }
1251
1252 spec = plugin->spec_data;
398454ed 1253 spec->shared_lib_handle = shared_lib_handle;
6871026b 1254 bt_object_get_ref_no_null_check(spec->shared_lib_handle);
55bb57e0
PP
1255 goto end;
1256
1257error:
65300d60 1258 BT_OBJECT_PUT_REF_AND_RESET(plugin);
55bb57e0
PP
1259
1260end:
1261 return plugin;
1262}
1263
52238017
MJ
1264static
1265size_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
55bb57e0 1281static
d24d5663 1282int bt_plugin_so_create_all_from_sections(
55bb57e0 1283 struct bt_plugin_so_shared_lib_handle *shared_lib_handle,
9736d991 1284 bool fail_on_load_error,
55bb57e0
PP
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,
9736d991
PP
1292 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end,
1293 struct bt_plugin_set **plugin_set_out)
55bb57e0 1294{
d24d5663 1295 int status = BT_FUNC_STATUS_OK;
55bb57e0
PP
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;
55bb57e0 1301
829fbd63 1302 BT_ASSERT(shared_lib_handle);
9736d991
PP
1303 BT_ASSERT(plugin_set_out);
1304 *plugin_set_out = NULL;
52238017
MJ
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);
3f7d4d90 1309 BT_LOGI("Creating all SO plugins from sections: "
3fe0bf43
PP
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);
9736d991
PP
1324 *plugin_set_out = bt_plugin_set_create();
1325 if (!*plugin_set_out) {
870631a2 1326 BT_LIB_LOGE_APPEND_CAUSE("Cannot create empty plugin set.");
d24d5663 1327 status = BT_FUNC_STATUS_MEMORY_ERROR;
55bb57e0
PP
1328 goto error;
1329 }
1330
52238017 1331 for (i = 0; i < descriptors_end - descriptors_begin; i++) {
55bb57e0
PP
1332 const struct __bt_plugin_descriptor *descriptor =
1333 descriptors_begin[i];
1334 struct bt_plugin *plugin;
1335
5084732e 1336 if (!descriptor) {
52238017
MJ
1337 continue;
1338 }
1339
7c0244d6
PP
1340 BT_LOGI("Creating plugin object for plugin: name=\"%s\"",
1341 descriptor->name);
55bb57e0
PP
1342 plugin = bt_plugin_so_create_empty(shared_lib_handle);
1343 if (!plugin) {
870631a2
PP
1344 BT_LIB_LOGE_APPEND_CAUSE(
1345 "Cannot create empty shared library handle.");
d24d5663 1346 status = BT_FUNC_STATUS_MEMORY_ERROR;
55bb57e0
PP
1347 goto error;
1348 }
1349
ea251e8b 1350 if (shared_lib_handle->path) {
9736d991
PP
1351 bt_plugin_set_path(plugin,
1352 shared_lib_handle->path->str);
55bb57e0
PP
1353 }
1354
9736d991
PP
1355 status = bt_plugin_so_init(plugin, fail_on_load_error,
1356 descriptor, attrs_begin, attrs_end,
1357 cc_descriptors_begin, cc_descriptors_end,
55bb57e0 1358 cc_descr_attrs_begin, cc_descr_attrs_end);
d24d5663 1359 if (status == BT_FUNC_STATUS_OK) {
9736d991
PP
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) {
50ad9320 1364 /*
9736d991
PP
1365 * bt_plugin_so_init() handles
1366 * `fail_on_load_error`, so this is a "real"
1367 * error.
50ad9320 1368 */
870631a2
PP
1369 BT_LIB_LOGW_APPEND_CAUSE(
1370 "Cannot initialize SO plugin object from sections.");
65300d60 1371 BT_OBJECT_PUT_REF_AND_RESET(plugin);
55bb57e0
PP
1372 goto error;
1373 }
1374
9736d991
PP
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);
d24d5663 1382 status = BT_FUNC_STATUS_NOT_FOUND;
55bb57e0
PP
1383 }
1384
1385 goto end;
1386
1387error:
9736d991
PP
1388 BT_ASSERT(status < 0);
1389 BT_OBJECT_PUT_REF_AND_RESET(*plugin_set_out);
55bb57e0
PP
1390
1391end:
9736d991 1392 return status;
55bb57e0
PP
1393}
1394
1395BT_HIDDEN
d24d5663 1396int bt_plugin_so_create_all_from_static(bool fail_on_load_error,
9736d991 1397 struct bt_plugin_set **plugin_set_out)
55bb57e0 1398{
d24d5663 1399 int status;
9736d991 1400 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
55bb57e0 1401
9736d991
PP
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);
d24d5663 1406 if (status != BT_FUNC_STATUS_OK) {
9736d991 1407 BT_ASSERT(!shared_lib_handle);
55bb57e0
PP
1408 goto end;
1409 }
1410
9736d991 1411 BT_ASSERT(shared_lib_handle);
3fe0bf43 1412 BT_LOGD_STR("Creating all SO plugins from built-in plugins.");
9736d991
PP
1413 status = bt_plugin_so_create_all_from_sections(shared_lib_handle,
1414 fail_on_load_error,
52238017
MJ
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(),
9736d991
PP
1422 __bt_get_end_section_component_class_descriptor_attributes(),
1423 plugin_set_out);
d24d5663 1424 BT_ASSERT((status == BT_FUNC_STATUS_OK && *plugin_set_out &&
9736d991 1425 (*plugin_set_out)->plugins->len > 0) || !*plugin_set_out);
55bb57e0
PP
1426
1427end:
65300d60 1428 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle);
9736d991 1429 return status;
55bb57e0
PP
1430}
1431
1432BT_HIDDEN
d24d5663 1433int bt_plugin_so_create_all_from_file(const char *path,
9736d991 1434 bool fail_on_load_error, struct bt_plugin_set **plugin_set_out)
55bb57e0
PP
1435{
1436 size_t path_len;
d24d5663 1437 int status;
55bb57e0
PP
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;
52238017
MJ
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);
c55a9f58 1454 bt_bool is_libtool_wrapper = BT_FALSE, is_shared_object = BT_FALSE;
55bb57e0
PP
1455 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
1456
3f7d4d90 1457 BT_ASSERT(path);
9736d991
PP
1458 BT_ASSERT(plugin_set_out);
1459 *plugin_set_out = NULL;
55bb57e0 1460 path_len = strlen(path);
4830a4bc
FD
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
3f7d4d90 1474 BT_LOGI("Trying to create all SO plugins from file: path=\"%s\"", path);
55bb57e0 1475 path_len++;
3f7d4d90 1476
55bb57e0 1477 /*
3f7d4d90
PP
1478 * Check if the file ends with a known plugin file type suffix
1479 * (i.e. .so or .la on Linux).
55bb57e0
PP
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) {
3fe0bf43 1488 /* Name indicates this is not a plugin file; not an error */
9736d991 1489 BT_LOGI("File is not an SO plugin file: path=\"%s\"", path);
d24d5663 1490 status = BT_FUNC_STATUS_NOT_FOUND;
55bb57e0
PP
1491 goto end;
1492 }
1493
9736d991
PP
1494 status = bt_plugin_so_shared_lib_handle_create(path,
1495 &shared_lib_handle);
d24d5663 1496 if (status != BT_FUNC_STATUS_OK) {
3f7d4d90 1497 /* bt_plugin_so_shared_lib_handle_create() logs more details */
9736d991 1498 BT_ASSERT(!shared_lib_handle);
55bb57e0
PP
1499 goto end;
1500 }
1501
52238017
MJ
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 {
9736d991
PP
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 */
3f7d4d90 1512 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
3fe0bf43 1513 "symbol=\"%s\"", path,
52238017 1514 "__bt_get_begin_section_plugin_descriptors");
d24d5663 1515 status = BT_FUNC_STATUS_NOT_FOUND;
55bb57e0
PP
1516 goto end;
1517 }
1518
9736d991
PP
1519 /*
1520 * If g_module_symbol() fails for any of the other symbols, fail
1521 * if `fail_on_load_error` is true.
1522 */
52238017
MJ
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 {
870631a2
PP
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");
b189a968 1532 status = BT_FUNC_STATUS_ERROR;
870631a2 1533 } else {
a0cdfce8 1534 BT_LIB_LOGW(
870631a2
PP
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
55bb57e0
PP
1541 goto end;
1542 }
1543
52238017
MJ
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 {
3f7d4d90 1548 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
3fe0bf43 1549 "symbol=\"%s\"", path,
52238017 1550 "__bt_get_begin_section_plugin_descriptor_attributes");
55bb57e0
PP
1551 }
1552
52238017
MJ
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 {
3f7d4d90 1557 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
3fe0bf43 1558 "symbol=\"%s\"", path,
52238017 1559 "__bt_get_end_section_plugin_descriptor_attributes");
55bb57e0
PP
1560 }
1561
1562 if ((!!attrs_begin - !!attrs_end) != 0) {
870631a2
PP
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);
b189a968 1572 status = BT_FUNC_STATUS_ERROR;
870631a2 1573 } else {
a0cdfce8 1574 BT_LIB_LOGW(
870631a2
PP
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
55bb57e0
PP
1585 goto end;
1586 }
1587
52238017
MJ
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 {
3f7d4d90 1592 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
3fe0bf43 1593 "symbol=\"%s\"", path,
52238017 1594 "__bt_get_begin_section_component_class_descriptors");
55bb57e0
PP
1595 }
1596
52238017
MJ
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 {
3f7d4d90 1601 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
3fe0bf43 1602 "symbol=\"%s\"", path,
52238017 1603 "__bt_get_end_section_component_class_descriptors");
55bb57e0
PP
1604 }
1605
1606 if ((!!cc_descriptors_begin - !!cc_descriptors_end) != 0) {
870631a2
PP
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);
b189a968 1616 status = BT_FUNC_STATUS_ERROR;
870631a2 1617 } else {
a0cdfce8 1618 BT_LIB_LOGW(
870631a2
PP
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
55bb57e0
PP
1629 goto end;
1630 }
1631
52238017
MJ
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 {
3f7d4d90 1636 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
3fe0bf43 1637 "symbol=\"%s\"", path,
52238017 1638 "__bt_get_begin_section_component_class_descriptor_attributes");
55bb57e0
PP
1639 }
1640
52238017
MJ
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 {
3f7d4d90 1645 BT_LOGI("Cannot resolve plugin symbol: path=\"%s\", "
3fe0bf43 1646 "symbol=\"%s\"", path,
52238017 1647 "__bt_get_end_section_component_class_descriptor_attributes");
55bb57e0
PP
1648 }
1649
1650 if ((!!cc_descr_attrs_begin - !!cc_descr_attrs_end) != 0) {
870631a2
PP
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);
b189a968 1660 status = BT_FUNC_STATUS_ERROR;
870631a2 1661 } else {
a0cdfce8 1662 BT_LIB_LOGW(
870631a2
PP
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
55bb57e0
PP
1673 goto end;
1674 }
1675
1676 /* Initialize plugin */
3fe0bf43 1677 BT_LOGD_STR("Initializing plugin object.");
9736d991
PP
1678 status = bt_plugin_so_create_all_from_sections(shared_lib_handle,
1679 fail_on_load_error,
55bb57e0
PP
1680 descriptors_begin, descriptors_end, attrs_begin, attrs_end,
1681 cc_descriptors_begin, cc_descriptors_end,
9736d991 1682 cc_descr_attrs_begin, cc_descr_attrs_end, plugin_set_out);
55bb57e0
PP
1683
1684end:
65300d60 1685 BT_OBJECT_PUT_REF_AND_RESET(shared_lib_handle);
9736d991 1686 return status;
55bb57e0
PP
1687}
1688
1689static
1690void plugin_comp_class_destroy_listener(struct bt_component_class *comp_class,
1691 void *data)
1692{
bfa9a4be 1693 bt_list_del(&comp_class->node);
65300d60 1694 BT_OBJECT_PUT_REF_AND_RESET(comp_class->so_handle);
3f7d4d90 1695 BT_LOGD("Component class destroyed: removed entry from list: "
3fe0bf43 1696 "comp-cls-addr=%p", comp_class);
55bb57e0
PP
1697}
1698
3230ee6b 1699void bt_plugin_so_on_add_component_class(struct bt_plugin *plugin,
55bb57e0
PP
1700 struct bt_component_class *comp_class)
1701{
55bb57e0
PP
1702 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
1703
f6ccaed9
PP
1704 BT_ASSERT(plugin->spec_data);
1705 BT_ASSERT(plugin->type == BT_PLUGIN_TYPE_SO);
55bb57e0 1706
bfa9a4be 1707 bt_list_add(&comp_class->node, &component_class_list);
398454ed 1708 comp_class->so_handle = spec->shared_lib_handle;
6871026b 1709 bt_object_get_ref_no_null_check(comp_class->so_handle);
55bb57e0
PP
1710
1711 /* Add our custom destroy listener */
3230ee6b 1712 bt_component_class_add_destroy_listener(comp_class,
55bb57e0 1713 plugin_comp_class_destroy_listener, NULL);
55bb57e0 1714}
This page took 0.151677 seconds and 4 git commands to generate.