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