Update include/babeltrace/babeltrace.h
[babeltrace.git] / lib / plugin / plugin-so.c
CommitLineData
55bb57e0
PP
1/*
2 * plugin-so.c
3 *
4 * Babeltrace Plugin (shared object)
5 *
6 * Copyright 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
8 *
9 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
3d9990ac 30#include <babeltrace/compiler-internal.h>
55bb57e0
PP
31#include <babeltrace/ref.h>
32#include <babeltrace/plugin/plugin-internal.h>
33#include <babeltrace/plugin/plugin-so-internal.h>
34#include <babeltrace/plugin/plugin-dev.h>
35#include <babeltrace/plugin/plugin-internal.h>
b2e0c907 36#include <babeltrace/graph/component-class-internal.h>
55bb57e0
PP
37#include <string.h>
38#include <stdbool.h>
39#include <glib.h>
40#include <gmodule.h>
41
42#define NATIVE_PLUGIN_SUFFIX ".so"
43#define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
44#define LIBTOOL_PLUGIN_SUFFIX ".la"
45#define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
46
47#define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
48 sizeof(LIBTOOL_PLUGIN_SUFFIX))
49
50#define SECTION_BEGIN(_name) (&(__start_##_name))
51#define SECTION_END(_name) (&(__stop_##_name))
52#define SECTION_ELEMENT_COUNT(_name) (SECTION_END(_name) - SECTION_BEGIN(_name))
53
54#define DECLARE_SECTION(_type, _name) \
55 extern _type __start_##_name __attribute((weak)); \
56 extern _type __stop_##_name __attribute((weak))
57
58DECLARE_SECTION(struct __bt_plugin_descriptor const *, __bt_plugin_descriptors);
59DECLARE_SECTION(struct __bt_plugin_descriptor_attribute const *, __bt_plugin_descriptor_attributes);
60DECLARE_SECTION(struct __bt_plugin_component_class_descriptor const *, __bt_plugin_component_class_descriptors);
61DECLARE_SECTION(struct __bt_plugin_component_class_descriptor_attribute const *, __bt_plugin_component_class_descriptor_attributes);
62
63/*
64 * This hash table, global to the library, maps component class pointers
65 * to shared library handles.
66 *
67 * The keys (component classes) are NOT owned by this hash table, whereas
68 * the values (shared library handles) are owned by this hash table.
69 *
70 * The keys are the component classes created with
71 * bt_plugin_add_component_class(). They keep the shared library handle
72 * object created by their plugin alive so that the plugin's code is
73 * not discarded when it could still be in use by living components
74 * created from those component classes:
75 *
76 * [component] --ref-> [component class] --through this HT-> [shlib handle]
77 *
78 * This hash table exists for two reasons:
79 *
80 * 1. To allow this application:
81 *
82 * my_plugins = bt_plugin_create_all_from_file("/path/to/my-plugin.so");
83 * // instantiate components from a plugin's component classes
84 * // put plugins and free my_plugins here
85 * // user code of instantiated components still exists
86 *
87 * 2. To decouple the plugin subsystem from the component subsystem:
88 * while plugins objects need to know component class objects, the
89 * opposite is not necessary, thus it makes no sense for a component
90 * class to keep a reference to the plugin object from which it was
91 * created.
92 *
93 * An entry is removed from this HT when a component class is destroyed
94 * thanks to a custom destroy listener. When the entry is removed, the
95 * GLib function calls the value destroy notifier of the HT, which is
96 * bt_put(). This decreases the reference count of the mapped shared
97 * library handle. Assuming the original plugin object which contained
98 * some component classes is put first, when the last component class is
99 * removed from this HT, the shared library handle object's reference
100 * count falls to zero and the shared library is finally closed.
101 */
102static
103GHashTable *comp_classes_to_shlib_handles;
104
105__attribute__((constructor)) static
106void init_comp_classes_to_shlib_handles(void) {
107 comp_classes_to_shlib_handles = g_hash_table_new_full(g_direct_hash,
108 g_direct_equal, NULL, bt_put);
109 assert(comp_classes_to_shlib_handles);
110}
111
112__attribute__((destructor)) static
113void fini_comp_classes_to_shlib_handles(void) {
114 if (comp_classes_to_shlib_handles) {
115 g_hash_table_destroy(comp_classes_to_shlib_handles);
116 }
117}
118
119static
120void bt_plugin_so_shared_lib_handle_destroy(struct bt_object *obj)
121{
122 struct bt_plugin_so_shared_lib_handle *shared_lib_handle;
123
124 assert(obj);
125 shared_lib_handle = container_of(obj,
126 struct bt_plugin_so_shared_lib_handle, base);
127
128 if (shared_lib_handle->init_called && shared_lib_handle->exit) {
129 enum bt_plugin_status status = shared_lib_handle->exit();
130
131 if (status < 0) {
132 const char *path = shared_lib_handle->path ?
133 shared_lib_handle->path->str : "[built-in]";
134
135 printf_verbose("Plugin in module `%s` exited with error %d\n",
136 path, status);
137 }
138 }
139
140 if (shared_lib_handle->module) {
141 if (!g_module_close(shared_lib_handle->module)) {
142 printf_error("Module close error: %s\n",
143 g_module_error());
144 }
145 }
146
147 if (shared_lib_handle->path) {
148 g_string_free(shared_lib_handle->path, TRUE);
149 }
150
151 g_free(shared_lib_handle);
152}
153
154static
155struct bt_plugin_so_shared_lib_handle *bt_plugin_so_shared_lib_handle_create(
156 const char *path)
157{
158 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
159
160 shared_lib_handle = g_new0(struct bt_plugin_so_shared_lib_handle, 1);
161 if (!shared_lib_handle) {
162 goto error;
163 }
164
165 bt_object_init(shared_lib_handle, bt_plugin_so_shared_lib_handle_destroy);
166
167 if (!path) {
168 goto end;
169 }
170
171 shared_lib_handle->path = g_string_new(path);
172 if (!shared_lib_handle->path) {
173 goto error;
174 }
175
176 shared_lib_handle->module = g_module_open(path, 0);
177 if (!shared_lib_handle->module) {
178 printf_verbose("Module open error: %s\n", g_module_error());
179 goto error;
180 }
181
182 goto end;
183
184error:
185 BT_PUT(shared_lib_handle);
186
187end:
188 return shared_lib_handle;
189}
190
6fbd4105 191static
55bb57e0
PP
192void bt_plugin_so_destroy_spec_data(struct bt_plugin *plugin)
193{
194 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
195
196 if (!plugin->spec_data) {
197 return;
198 }
199
200 assert(plugin->type == BT_PLUGIN_TYPE_SO);
201 assert(spec);
202 BT_PUT(spec->shared_lib_handle);
203 g_free(plugin->spec_data);
204 plugin->spec_data = NULL;
205}
206
207/*
208 * This function does the following:
209 *
210 * 1. Iterate on the plugin descriptor attributes section and set the
211 * plugin's attributes depending on the attribute types. This
212 * includes the name of the plugin, its description, and its
213 * initialization function, for example.
214 *
215 * 2. Iterate on the component class descriptors section and create one
216 * "full descriptor" (temporary structure) for each one that is found
217 * and attached to our plugin descriptor.
218 *
219 * 3. Iterate on the component class descriptor attributes section and
220 * set the corresponding full descriptor's attributes depending on
221 * the attribute types. This includes the description of the
222 * component class, as well as its initialization and destroy
223 * methods.
224 *
225 * 4. Call the user's plugin initialization function, if any is
226 * defined.
227 *
228 * 5. For each full component class descriptor, create a component class
229 * object, set its optional attributes, and add it to the plugin
230 * object.
231 *
232 * 6. Freeze the plugin object.
233 */
234static
235enum bt_plugin_status bt_plugin_so_init(
236 struct bt_plugin *plugin,
237 const struct __bt_plugin_descriptor *descriptor,
238 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
239 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
240 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
241 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
242 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
243 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
244{
245 /*
246 * This structure's members point to the plugin's memory
247 * (do NOT free).
248 */
249 struct comp_class_full_descriptor {
250 const struct __bt_plugin_component_class_descriptor *descriptor;
251 const char *description;
279b3f15 252 const char *help;
55bb57e0 253 bt_component_class_init_method init_method;
64cadc66 254 bt_component_class_finalize_method finalize_method;
a67681c1 255 bt_component_class_query_method query_method;
72b913fb 256 bt_component_class_accept_port_connection_method accept_port_connection_method;
0d8b4d8e 257 bt_component_class_port_connected_method port_connected_method;
72b913fb 258 bt_component_class_port_disconnected_method port_disconnected_method;
55bb57e0
PP
259 struct bt_component_class_iterator_methods iterator_methods;
260 };
261
262 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
263 struct __bt_plugin_descriptor_attribute const * const *cur_attr_ptr;
264 struct __bt_plugin_component_class_descriptor const * const *cur_cc_descr_ptr;
265 struct __bt_plugin_component_class_descriptor_attribute const * const *cur_cc_descr_attr_ptr;
266 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
267 GArray *comp_class_full_descriptors;
268 size_t i;
269 int ret;
270
271 comp_class_full_descriptors = g_array_new(FALSE, TRUE,
272 sizeof(struct comp_class_full_descriptor));
273 if (!comp_class_full_descriptors) {
274 status = BT_PLUGIN_STATUS_ERROR;
275 goto end;
276 }
277
278 /* Set mandatory attributes */
279 spec->descriptor = descriptor;
280 bt_plugin_set_name(plugin, descriptor->name);
281
282 /*
283 * Find and set optional attributes attached to this plugin
284 * descriptor.
285 */
286 for (cur_attr_ptr = attrs_begin; cur_attr_ptr != attrs_end; cur_attr_ptr++) {
287 const struct __bt_plugin_descriptor_attribute *cur_attr =
288 *cur_attr_ptr;
289
290 if (cur_attr->plugin_descriptor != descriptor) {
291 continue;
292 }
293
294 switch (cur_attr->type) {
295 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT:
296 spec->init = cur_attr->value.init;
297 break;
298 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT:
299 spec->shared_lib_handle->exit = cur_attr->value.exit;
300 break;
301 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR:
302 bt_plugin_set_author(plugin, cur_attr->value.author);
303 break;
304 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE:
305 bt_plugin_set_license(plugin, cur_attr->value.license);
306 break;
307 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
308 bt_plugin_set_description(plugin, cur_attr->value.description);
309 break;
310 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION:
311 bt_plugin_set_version(plugin,
312 (unsigned int) cur_attr->value.version.major,
313 (unsigned int) cur_attr->value.version.minor,
314 (unsigned int) cur_attr->value.version.patch,
315 cur_attr->value.version.extra);
316 break;
317 default:
318 printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for plugin %s\n",
319 cur_attr->type_name, cur_attr->type,
320 descriptor->name);
321 break;
322 }
323 }
324
325 /*
326 * Find component class descriptors attached to this plugin
327 * descriptor and initialize corresponding full component class
328 * descriptors in the array.
329 */
330 for (cur_cc_descr_ptr = cc_descriptors_begin; cur_cc_descr_ptr != cc_descriptors_end; cur_cc_descr_ptr++) {
331 const struct __bt_plugin_component_class_descriptor *cur_cc_descr =
332 *cur_cc_descr_ptr;
333 struct comp_class_full_descriptor full_descriptor = {0};
334
335 if (cur_cc_descr->plugin_descriptor != descriptor) {
336 continue;
337 }
338
339 full_descriptor.descriptor = cur_cc_descr;
340 g_array_append_val(comp_class_full_descriptors,
341 full_descriptor);
342 }
343
344 /*
345 * Find component class descriptor attributes attached to this
346 * plugin descriptor and update corresponding full component
347 * class descriptors in the array.
348 */
349 for (cur_cc_descr_attr_ptr = cc_descr_attrs_begin; cur_cc_descr_attr_ptr != cc_descr_attrs_end; cur_cc_descr_attr_ptr++) {
350 const struct __bt_plugin_component_class_descriptor_attribute *cur_cc_descr_attr =
351 *cur_cc_descr_attr_ptr;
352
353 if (cur_cc_descr_attr->comp_class_descriptor->plugin_descriptor !=
354 descriptor) {
355 continue;
356 }
357
358 /* Find the corresponding component class descriptor entry */
359 for (i = 0; i < comp_class_full_descriptors->len; i++) {
360 struct comp_class_full_descriptor *cc_full_descr =
361 &g_array_index(comp_class_full_descriptors,
362 struct comp_class_full_descriptor, i);
363
364 if (cur_cc_descr_attr->comp_class_descriptor ==
365 cc_full_descr->descriptor) {
366 switch (cur_cc_descr_attr->type) {
367 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
368 cc_full_descr->description =
369 cur_cc_descr_attr->value.description;
370 break;
279b3f15
PP
371 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP:
372 cc_full_descr->help =
373 cur_cc_descr_attr->value.help;
374 break;
55bb57e0
PP
375 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INIT_METHOD:
376 cc_full_descr->init_method =
377 cur_cc_descr_attr->value.init_method;
378 break;
64cadc66
PP
379 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD:
380 cc_full_descr->finalize_method =
381 cur_cc_descr_attr->value.finalize_method;
55bb57e0 382 break;
a67681c1
PP
383 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD:
384 cc_full_descr->query_method =
385 cur_cc_descr_attr->value.query_method;
8463eac2 386 break;
72b913fb
PP
387 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_ACCEPT_PORT_CONNECTION_METHOD:
388 cc_full_descr->accept_port_connection_method =
389 cur_cc_descr_attr->value.accept_port_connection_method;
390 break;
0d8b4d8e
PP
391 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD:
392 cc_full_descr->port_connected_method =
393 cur_cc_descr_attr->value.port_connected_method;
394 break;
72b913fb
PP
395 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_DISCONNECTED_METHOD:
396 cc_full_descr->port_disconnected_method =
397 cur_cc_descr_attr->value.port_disconnected_method;
55bb57e0
PP
398 break;
399 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_INIT_METHOD:
400 cc_full_descr->iterator_methods.init =
401 cur_cc_descr_attr->value.notif_iter_init_method;
402 break;
64cadc66
PP
403 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_FINALIZE_METHOD:
404 cc_full_descr->iterator_methods.finalize =
405 cur_cc_descr_attr->value.notif_iter_finalize_method;
55bb57e0
PP
406 break;
407 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_SEEK_TIME_METHOD:
408 cc_full_descr->iterator_methods.seek_time =
409 cur_cc_descr_attr->value.notif_iter_seek_time_method;
410 break;
411 default:
412 printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for component class %s (type %d) in plugin %s\n",
413 cur_cc_descr_attr->type_name,
414 cur_cc_descr_attr->type,
415 cur_cc_descr_attr->comp_class_descriptor->name,
416 cur_cc_descr_attr->comp_class_descriptor->type,
417 descriptor->name);
418 break;
419 }
420 }
421 }
422 }
423
424 /* Initialize plugin */
425 if (spec->init) {
426 status = spec->init(plugin);
427 if (status < 0) {
428 printf_verbose("Plugin `%s` initialization error: %d\n",
429 bt_plugin_get_name(plugin), status);
430 goto end;
431 }
432 }
433
434 spec->shared_lib_handle->init_called = true;
435
436 /* Add described component classes to plugin */
437 for (i = 0; i < comp_class_full_descriptors->len; i++) {
438 struct comp_class_full_descriptor *cc_full_descr =
439 &g_array_index(comp_class_full_descriptors,
440 struct comp_class_full_descriptor, i);
441 struct bt_component_class *comp_class;
442
443 switch (cc_full_descr->descriptor->type) {
444 case BT_COMPONENT_CLASS_TYPE_SOURCE:
445 comp_class = bt_component_class_source_create(
446 cc_full_descr->descriptor->name,
55bb57e0
PP
447 cc_full_descr->descriptor->methods.source.notif_iter_next);
448 break;
449 case BT_COMPONENT_CLASS_TYPE_FILTER:
450 comp_class = bt_component_class_filter_create(
451 cc_full_descr->descriptor->name,
55bb57e0
PP
452 cc_full_descr->descriptor->methods.source.notif_iter_next);
453 break;
454 case BT_COMPONENT_CLASS_TYPE_SINK:
455 comp_class = bt_component_class_sink_create(
456 cc_full_descr->descriptor->name,
457 cc_full_descr->descriptor->methods.sink.consume);
458 break;
459 default:
460 printf_verbose("WARNING: Unknown component class type %d for component class %s in plugin %s\n",
461 cc_full_descr->descriptor->type,
462 cc_full_descr->descriptor->name,
463 descriptor->name);
464 continue;
465 }
466
467 if (!comp_class) {
468 status = BT_PLUGIN_STATUS_ERROR;
469 goto end;
470 }
471
472 if (cc_full_descr->description) {
473 ret = bt_component_class_set_description(comp_class,
474 cc_full_descr->description);
475 if (ret) {
476 status = BT_PLUGIN_STATUS_ERROR;
477 BT_PUT(comp_class);
478 goto end;
479 }
480 }
481
279b3f15
PP
482 if (cc_full_descr->help) {
483 ret = bt_component_class_set_help(comp_class,
484 cc_full_descr->help);
485 if (ret) {
486 status = BT_PLUGIN_STATUS_ERROR;
487 BT_PUT(comp_class);
488 goto end;
489 }
490 }
491
55bb57e0
PP
492 if (cc_full_descr->init_method) {
493 ret = bt_component_class_set_init_method(comp_class,
494 cc_full_descr->init_method);
495 if (ret) {
496 status = BT_PLUGIN_STATUS_ERROR;
497 BT_PUT(comp_class);
498 goto end;
499 }
500 }
501
64cadc66
PP
502 if (cc_full_descr->finalize_method) {
503 ret = bt_component_class_set_finalize_method(comp_class,
504 cc_full_descr->finalize_method);
55bb57e0
PP
505 if (ret) {
506 status = BT_PLUGIN_STATUS_ERROR;
507 BT_PUT(comp_class);
508 goto end;
509 }
510 }
511
a67681c1
PP
512 if (cc_full_descr->query_method) {
513 ret = bt_component_class_set_query_method(
514 comp_class, cc_full_descr->query_method);
8463eac2
PP
515 if (ret) {
516 status = BT_PLUGIN_STATUS_ERROR;
517 BT_PUT(comp_class);
518 goto end;
519 }
520 }
521
72b913fb
PP
522 if (cc_full_descr->accept_port_connection_method) {
523 ret = bt_component_class_set_accept_port_connection_method(
524 comp_class, cc_full_descr->accept_port_connection_method);
525 if (ret) {
526 status = BT_PLUGIN_STATUS_ERROR;
527 BT_PUT(comp_class);
528 goto end;
529 }
530 }
531
0d8b4d8e
PP
532 if (cc_full_descr->port_connected_method) {
533 ret = bt_component_class_set_port_connected_method(
534 comp_class, cc_full_descr->port_connected_method);
535 if (ret) {
536 status = BT_PLUGIN_STATUS_ERROR;
537 BT_PUT(comp_class);
538 goto end;
539 }
540 }
541
72b913fb
PP
542 if (cc_full_descr->port_disconnected_method) {
543 ret = bt_component_class_set_port_disconnected_method(
544 comp_class, cc_full_descr->port_disconnected_method);
2d41b99e
JG
545 if (ret) {
546 status = BT_PLUGIN_STATUS_ERROR;
547 BT_PUT(comp_class);
548 goto end;
549 }
550 }
551
55bb57e0
PP
552 switch (cc_full_descr->descriptor->type) {
553 case BT_COMPONENT_CLASS_TYPE_SOURCE:
554 if (cc_full_descr->iterator_methods.init) {
555 ret = bt_component_class_source_set_notification_iterator_init_method(
556 comp_class,
557 cc_full_descr->iterator_methods.init);
558 if (ret) {
559 status = BT_PLUGIN_STATUS_ERROR;
560 BT_PUT(comp_class);
561 goto end;
562 }
563 }
564
64cadc66
PP
565 if (cc_full_descr->iterator_methods.finalize) {
566 ret = bt_component_class_source_set_notification_iterator_finalize_method(
55bb57e0 567 comp_class,
64cadc66 568 cc_full_descr->iterator_methods.finalize);
55bb57e0
PP
569 if (ret) {
570 status = BT_PLUGIN_STATUS_ERROR;
571 BT_PUT(comp_class);
572 goto end;
573 }
574 }
575
576 if (cc_full_descr->iterator_methods.seek_time) {
577 ret = bt_component_class_source_set_notification_iterator_seek_time_method(
578 comp_class,
579 cc_full_descr->iterator_methods.seek_time);
580 if (ret) {
581 status = BT_PLUGIN_STATUS_ERROR;
582 BT_PUT(comp_class);
583 goto end;
584 }
585 }
586 break;
587 case BT_COMPONENT_CLASS_TYPE_FILTER:
55bb57e0
PP
588 if (cc_full_descr->iterator_methods.init) {
589 ret = bt_component_class_filter_set_notification_iterator_init_method(
590 comp_class,
591 cc_full_descr->iterator_methods.init);
592 if (ret) {
593 status = BT_PLUGIN_STATUS_ERROR;
594 BT_PUT(comp_class);
595 goto end;
596 }
597 }
598
64cadc66
PP
599 if (cc_full_descr->iterator_methods.finalize) {
600 ret = bt_component_class_filter_set_notification_iterator_finalize_method(
55bb57e0 601 comp_class,
64cadc66 602 cc_full_descr->iterator_methods.finalize);
55bb57e0
PP
603 if (ret) {
604 status = BT_PLUGIN_STATUS_ERROR;
605 BT_PUT(comp_class);
606 goto end;
607 }
608 }
609
610 if (cc_full_descr->iterator_methods.seek_time) {
611 ret = bt_component_class_filter_set_notification_iterator_seek_time_method(
612 comp_class,
613 cc_full_descr->iterator_methods.seek_time);
614 if (ret) {
615 status = BT_PLUGIN_STATUS_ERROR;
616 BT_PUT(comp_class);
617 goto end;
618 }
619 }
620 break;
621 case BT_COMPONENT_CLASS_TYPE_SINK:
55bb57e0
PP
622 break;
623 default:
624 assert(false);
625 break;
626 }
627
628 /*
629 * Add component class to the plugin object.
630 *
631 * This will call back
632 * bt_plugin_so_on_add_component_class() so that we can
633 * add a mapping in comp_classes_to_shlib_handles when
634 * we know the component class is successfully added.
635 */
636 status = bt_plugin_add_component_class(plugin,
637 comp_class);
638 BT_PUT(comp_class);
639 if (status < 0) {
640 printf_verbose("Cannot add component class %s (type %d) to plugin `%s`: status = %d\n",
641 cc_full_descr->descriptor->name,
642 cc_full_descr->descriptor->type,
643 bt_plugin_get_name(plugin), status);
644 goto end;
645 }
646 }
647
648 /*
649 * All the plugin's component classes should be added at this
650 * point. We freeze the plugin so that it's not possible to add
651 * component classes to this plugin object after this stage
652 * (plugin object becomes immutable).
653 */
654 bt_plugin_freeze(plugin);
655
656end:
657 g_array_free(comp_class_full_descriptors, TRUE);
658 return status;
659}
660
661static
662struct bt_plugin *bt_plugin_so_create_empty(
663 struct bt_plugin_so_shared_lib_handle *shared_lib_handle)
664{
665 struct bt_plugin *plugin;
666 struct bt_plugin_so_spec_data *spec;
667
668 plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_SO);
669 if (!plugin) {
670 goto error;
671 }
672
6fbd4105 673 plugin->destroy_spec_data = bt_plugin_so_destroy_spec_data;
55bb57e0
PP
674 plugin->spec_data = g_new0(struct bt_plugin_so_spec_data, 1);
675 if (!plugin->spec_data) {
676 goto error;
677 }
678
679 spec = plugin->spec_data;
680 spec->shared_lib_handle = bt_get(shared_lib_handle);
681 goto end;
682
683error:
684 BT_PUT(plugin);
685
686end:
687 return plugin;
688}
689
690static
a8ff38ef 691struct bt_plugin_set *bt_plugin_so_create_all_from_sections(
55bb57e0
PP
692 struct bt_plugin_so_shared_lib_handle *shared_lib_handle,
693 struct __bt_plugin_descriptor const * const *descriptors_begin,
694 struct __bt_plugin_descriptor const * const *descriptors_end,
695 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
696 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
697 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
698 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
699 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
700 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
701{
702 size_t descriptor_count;
703 size_t attrs_count;
704 size_t cc_descriptors_count;
705 size_t cc_descr_attrs_count;
706 size_t i;
a8ff38ef 707 struct bt_plugin_set *plugin_set = NULL;
55bb57e0
PP
708
709 descriptor_count = descriptors_end - descriptors_begin;
710 attrs_count = attrs_end - attrs_begin;
711 cc_descriptors_count = cc_descriptors_end - cc_descriptors_begin;
712 cc_descr_attrs_count = cc_descr_attrs_end - cc_descr_attrs_begin;
713 printf_verbose("Section: Plugin descriptors: [%p - %p], (%zu elements)\n",
714 descriptors_begin, descriptors_end, descriptor_count);
715 printf_verbose("Section: Plugin descriptor attributes: [%p - %p], (%zu elements)\n",
716 attrs_begin, attrs_end, attrs_count);
717 printf_verbose("Section: Plugin component class descriptors: [%p - %p], (%zu elements)\n",
718 cc_descriptors_begin, cc_descriptors_end, cc_descriptors_count);
719 printf_verbose("Section: Plugin component class descriptor attributes: [%p - %p], (%zu elements)\n",
720 cc_descr_attrs_begin, cc_descr_attrs_end, cc_descr_attrs_count);
a8ff38ef
PP
721 plugin_set = bt_plugin_set_create();
722 if (!plugin_set) {
55bb57e0
PP
723 goto error;
724 }
725
726 for (i = 0; i < descriptor_count; i++) {
727 enum bt_plugin_status status;
728 const struct __bt_plugin_descriptor *descriptor =
729 descriptors_begin[i];
730 struct bt_plugin *plugin;
731
732 printf_verbose("Loading plugin %s (ABI %d.%d)\n", descriptor->name,
733 descriptor->major, descriptor->minor);
734
735 if (descriptor->major > __BT_PLUGIN_VERSION_MAJOR) {
736 printf_error("Unknown plugin's major version: %d\n",
737 descriptor->major);
738 goto error;
739 }
740
741 plugin = bt_plugin_so_create_empty(shared_lib_handle);
742 if (!plugin) {
743 printf_error("Cannot allocate plugin object for plugin %s\n",
744 descriptor->name);
745 goto error;
746 }
747
748 if (shared_lib_handle && shared_lib_handle->path) {
749 bt_plugin_set_path(plugin, shared_lib_handle->path->str);
750 }
751
752 status = bt_plugin_so_init(plugin, descriptor, attrs_begin,
753 attrs_end, cc_descriptors_begin, cc_descriptors_end,
754 cc_descr_attrs_begin, cc_descr_attrs_end);
755 if (status < 0) {
756 printf_error("Cannot initialize plugin object %s\n",
757 descriptor->name);
758 BT_PUT(plugin);
759 goto error;
760 }
761
a8ff38ef
PP
762 /* Add to plugin set */
763 bt_plugin_set_add_plugin(plugin_set, plugin);
764 bt_put(plugin);
55bb57e0
PP
765 }
766
767 goto end;
768
769error:
a8ff38ef 770 BT_PUT(plugin_set);
55bb57e0
PP
771
772end:
a8ff38ef 773 return plugin_set;
55bb57e0
PP
774}
775
776BT_HIDDEN
a8ff38ef 777struct bt_plugin_set *bt_plugin_so_create_all_from_static(void)
55bb57e0 778{
a8ff38ef 779 struct bt_plugin_set *plugin_set = NULL;
55bb57e0
PP
780 struct bt_plugin_so_shared_lib_handle *shared_lib_handle =
781 bt_plugin_so_shared_lib_handle_create(NULL);
782
783 if (!shared_lib_handle) {
784 goto end;
785 }
786
a8ff38ef 787 plugin_set = bt_plugin_so_create_all_from_sections(shared_lib_handle,
55bb57e0
PP
788 SECTION_BEGIN(__bt_plugin_descriptors),
789 SECTION_END(__bt_plugin_descriptors),
790 SECTION_BEGIN(__bt_plugin_descriptor_attributes),
791 SECTION_END(__bt_plugin_descriptor_attributes),
792 SECTION_BEGIN(__bt_plugin_component_class_descriptors),
793 SECTION_END(__bt_plugin_component_class_descriptors),
794 SECTION_BEGIN(__bt_plugin_component_class_descriptor_attributes),
795 SECTION_END(__bt_plugin_component_class_descriptor_attributes));
796
797end:
798 BT_PUT(shared_lib_handle);
799
a8ff38ef 800 return plugin_set;
55bb57e0
PP
801}
802
803BT_HIDDEN
a8ff38ef 804struct bt_plugin_set *bt_plugin_so_create_all_from_file(const char *path)
55bb57e0
PP
805{
806 size_t path_len;
a8ff38ef 807 struct bt_plugin_set *plugin_set = NULL;
55bb57e0
PP
808 struct __bt_plugin_descriptor const * const *descriptors_begin = NULL;
809 struct __bt_plugin_descriptor const * const *descriptors_end = NULL;
810 struct __bt_plugin_descriptor_attribute const * const *attrs_begin = NULL;
811 struct __bt_plugin_descriptor_attribute const * const *attrs_end = NULL;
812 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin = NULL;
813 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end = NULL;
814 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin = NULL;
815 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end = NULL;
816 bool is_libtool_wrapper = false, is_shared_object = false;
817 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
818
819 if (!path) {
820 goto end;
821 }
822
823 path_len = strlen(path);
824 if (path_len <= PLUGIN_SUFFIX_LEN) {
825 goto end;
826 }
827
828 path_len++;
829 /*
830 * Check if the file ends with a known plugin file type suffix (i.e. .so
831 * or .la on Linux).
832 */
833 is_libtool_wrapper = !strncmp(LIBTOOL_PLUGIN_SUFFIX,
834 path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN,
835 LIBTOOL_PLUGIN_SUFFIX_LEN);
836 is_shared_object = !strncmp(NATIVE_PLUGIN_SUFFIX,
837 path + path_len - NATIVE_PLUGIN_SUFFIX_LEN,
838 NATIVE_PLUGIN_SUFFIX_LEN);
839 if (!is_shared_object && !is_libtool_wrapper) {
840 /* Name indicates that this is not a plugin file. */
841 goto end;
842 }
843
844 shared_lib_handle = bt_plugin_so_shared_lib_handle_create(path);
845 if (!shared_lib_handle) {
846 goto end;
847 }
848
849 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_descriptors",
850 (gpointer *) &descriptors_begin)) {
851 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
852 "__start___bt_plugin_descriptors",
853 g_module_name(shared_lib_handle->module));
854 goto end;
855 }
856
857 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_descriptors",
858 (gpointer *) &descriptors_end)) {
859 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
860 "__stop___bt_plugin_descriptors",
861 g_module_name(shared_lib_handle->module));
862 goto end;
863 }
864
865 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_descriptor_attributes",
866 (gpointer *) &attrs_begin)) {
867 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
868 "__start___bt_plugin_descriptor_attributes",
869 g_module_name(shared_lib_handle->module));
870 }
871
872 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_descriptor_attributes",
873 (gpointer *) &attrs_end)) {
874 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
875 "__stop___bt_plugin_descriptor_attributes",
876 g_module_name(shared_lib_handle->module));
877 }
878
879 if ((!!attrs_begin - !!attrs_end) != 0) {
880 printf_verbose("Found __start___bt_plugin_descriptor_attributes or __stop___bt_plugin_descriptor_attributes symbol, but not both in %s\n",
881 g_module_name(shared_lib_handle->module));
882 goto end;
883 }
884
885 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_component_class_descriptors",
886 (gpointer *) &cc_descriptors_begin)) {
887 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
888 "__start___bt_plugin_component_class_descriptors",
889 g_module_name(shared_lib_handle->module));
890 }
891
892 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_component_class_descriptors",
893 (gpointer *) &cc_descriptors_end)) {
894 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
895 "__stop___bt_plugin_component_class_descriptors",
896 g_module_name(shared_lib_handle->module));
897 }
898
899 if ((!!cc_descriptors_begin - !!cc_descriptors_end) != 0) {
900 printf_verbose("Found __start___bt_plugin_component_class_descriptors or __stop___bt_plugin_component_class_descriptors symbol, but not both in %s\n",
901 g_module_name(shared_lib_handle->module));
902 goto end;
903 }
904
905 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_component_class_descriptor_attributes",
906 (gpointer *) &cc_descr_attrs_begin)) {
907 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
908 "__start___bt_plugin_component_class_descriptor_attributes",
909 g_module_name(shared_lib_handle->module));
910 }
911
912 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_component_class_descriptor_attributes",
913 (gpointer *) &cc_descr_attrs_end)) {
914 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
915 "__stop___bt_plugin_component_class_descriptor_attributes",
916 g_module_name(shared_lib_handle->module));
917 }
918
919 if ((!!cc_descr_attrs_begin - !!cc_descr_attrs_end) != 0) {
920 printf_verbose("Found __start___bt_plugin_component_class_descriptor_attributes or __stop___bt_plugin_component_class_descriptor_attributes symbol, but not both in %s\n",
921 g_module_name(shared_lib_handle->module));
922 goto end;
923 }
924
925 /* Initialize plugin */
a8ff38ef 926 plugin_set = bt_plugin_so_create_all_from_sections(shared_lib_handle,
55bb57e0
PP
927 descriptors_begin, descriptors_end, attrs_begin, attrs_end,
928 cc_descriptors_begin, cc_descriptors_end,
929 cc_descr_attrs_begin, cc_descr_attrs_end);
930
931end:
932 BT_PUT(shared_lib_handle);
a8ff38ef 933 return plugin_set;
55bb57e0
PP
934}
935
936static
937void plugin_comp_class_destroy_listener(struct bt_component_class *comp_class,
938 void *data)
939{
940 gboolean exists = g_hash_table_remove(comp_classes_to_shlib_handles,
941 comp_class);
942 assert(exists);
943}
944
945BT_HIDDEN
3230ee6b 946void bt_plugin_so_on_add_component_class(struct bt_plugin *plugin,
55bb57e0
PP
947 struct bt_component_class *comp_class)
948{
55bb57e0
PP
949 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
950
951 assert(plugin->spec_data);
952 assert(plugin->type == BT_PLUGIN_TYPE_SO);
953
954 /* Map component class pointer to shared lib handle in global HT */
955 g_hash_table_insert(comp_classes_to_shlib_handles, comp_class,
956 bt_get(spec->shared_lib_handle));
957
958 /* Add our custom destroy listener */
3230ee6b 959 bt_component_class_add_destroy_listener(comp_class,
55bb57e0 960 plugin_comp_class_destroy_listener, NULL);
55bb57e0 961}
This page took 0.062433 seconds and 4 git commands to generate.