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