Add `babeltrace convert` argument tests
[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
30#include <babeltrace/compiler.h>
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>
36#include <babeltrace/component/component-class-internal.h>
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
191BT_HIDDEN
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
PP
253 bt_component_class_init_method init_method;
254 bt_component_class_destroy_method destroy_method;
a67681c1 255 bt_component_class_query_method query_method;
2d41b99e 256 bt_component_class_new_connection_method new_connection_method;
55bb57e0
PP
257 struct bt_component_class_iterator_methods iterator_methods;
258 };
259
260 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
261 struct __bt_plugin_descriptor_attribute const * const *cur_attr_ptr;
262 struct __bt_plugin_component_class_descriptor const * const *cur_cc_descr_ptr;
263 struct __bt_plugin_component_class_descriptor_attribute const * const *cur_cc_descr_attr_ptr;
264 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
265 GArray *comp_class_full_descriptors;
266 size_t i;
267 int ret;
268
269 comp_class_full_descriptors = g_array_new(FALSE, TRUE,
270 sizeof(struct comp_class_full_descriptor));
271 if (!comp_class_full_descriptors) {
272 status = BT_PLUGIN_STATUS_ERROR;
273 goto end;
274 }
275
276 /* Set mandatory attributes */
277 spec->descriptor = descriptor;
278 bt_plugin_set_name(plugin, descriptor->name);
279
280 /*
281 * Find and set optional attributes attached to this plugin
282 * descriptor.
283 */
284 for (cur_attr_ptr = attrs_begin; cur_attr_ptr != attrs_end; cur_attr_ptr++) {
285 const struct __bt_plugin_descriptor_attribute *cur_attr =
286 *cur_attr_ptr;
287
288 if (cur_attr->plugin_descriptor != descriptor) {
289 continue;
290 }
291
292 switch (cur_attr->type) {
293 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT:
294 spec->init = cur_attr->value.init;
295 break;
296 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT:
297 spec->shared_lib_handle->exit = cur_attr->value.exit;
298 break;
299 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR:
300 bt_plugin_set_author(plugin, cur_attr->value.author);
301 break;
302 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE:
303 bt_plugin_set_license(plugin, cur_attr->value.license);
304 break;
305 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
306 bt_plugin_set_description(plugin, cur_attr->value.description);
307 break;
308 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION:
309 bt_plugin_set_version(plugin,
310 (unsigned int) cur_attr->value.version.major,
311 (unsigned int) cur_attr->value.version.minor,
312 (unsigned int) cur_attr->value.version.patch,
313 cur_attr->value.version.extra);
314 break;
315 default:
316 printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for plugin %s\n",
317 cur_attr->type_name, cur_attr->type,
318 descriptor->name);
319 break;
320 }
321 }
322
323 /*
324 * Find component class descriptors attached to this plugin
325 * descriptor and initialize corresponding full component class
326 * descriptors in the array.
327 */
328 for (cur_cc_descr_ptr = cc_descriptors_begin; cur_cc_descr_ptr != cc_descriptors_end; cur_cc_descr_ptr++) {
329 const struct __bt_plugin_component_class_descriptor *cur_cc_descr =
330 *cur_cc_descr_ptr;
331 struct comp_class_full_descriptor full_descriptor = {0};
332
333 if (cur_cc_descr->plugin_descriptor != descriptor) {
334 continue;
335 }
336
337 full_descriptor.descriptor = cur_cc_descr;
338 g_array_append_val(comp_class_full_descriptors,
339 full_descriptor);
340 }
341
342 /*
343 * Find component class descriptor attributes attached to this
344 * plugin descriptor and update corresponding full component
345 * class descriptors in the array.
346 */
347 for (cur_cc_descr_attr_ptr = cc_descr_attrs_begin; cur_cc_descr_attr_ptr != cc_descr_attrs_end; cur_cc_descr_attr_ptr++) {
348 const struct __bt_plugin_component_class_descriptor_attribute *cur_cc_descr_attr =
349 *cur_cc_descr_attr_ptr;
350
351 if (cur_cc_descr_attr->comp_class_descriptor->plugin_descriptor !=
352 descriptor) {
353 continue;
354 }
355
356 /* Find the corresponding component class descriptor entry */
357 for (i = 0; i < comp_class_full_descriptors->len; i++) {
358 struct comp_class_full_descriptor *cc_full_descr =
359 &g_array_index(comp_class_full_descriptors,
360 struct comp_class_full_descriptor, i);
361
362 if (cur_cc_descr_attr->comp_class_descriptor ==
363 cc_full_descr->descriptor) {
364 switch (cur_cc_descr_attr->type) {
365 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
366 cc_full_descr->description =
367 cur_cc_descr_attr->value.description;
368 break;
279b3f15
PP
369 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP:
370 cc_full_descr->help =
371 cur_cc_descr_attr->value.help;
372 break;
55bb57e0
PP
373 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INIT_METHOD:
374 cc_full_descr->init_method =
375 cur_cc_descr_attr->value.init_method;
376 break;
377 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESTROY_METHOD:
378 cc_full_descr->destroy_method =
379 cur_cc_descr_attr->value.destroy_method;
380 break;
a67681c1
PP
381 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD:
382 cc_full_descr->query_method =
383 cur_cc_descr_attr->value.query_method;
8463eac2 384 break;
2d41b99e
JG
385 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NEW_CONNECTION_METHOD:
386 cc_full_descr->new_connection_method =
387 cur_cc_descr_attr->value.new_connection_method;
55bb57e0
PP
388 break;
389 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_INIT_METHOD:
390 cc_full_descr->iterator_methods.init =
391 cur_cc_descr_attr->value.notif_iter_init_method;
392 break;
393 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_DESTROY_METHOD:
394 cc_full_descr->iterator_methods.destroy =
395 cur_cc_descr_attr->value.notif_iter_destroy_method;
396 break;
397 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_SEEK_TIME_METHOD:
398 cc_full_descr->iterator_methods.seek_time =
399 cur_cc_descr_attr->value.notif_iter_seek_time_method;
400 break;
401 default:
402 printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for component class %s (type %d) in plugin %s\n",
403 cur_cc_descr_attr->type_name,
404 cur_cc_descr_attr->type,
405 cur_cc_descr_attr->comp_class_descriptor->name,
406 cur_cc_descr_attr->comp_class_descriptor->type,
407 descriptor->name);
408 break;
409 }
410 }
411 }
412 }
413
414 /* Initialize plugin */
415 if (spec->init) {
416 status = spec->init(plugin);
417 if (status < 0) {
418 printf_verbose("Plugin `%s` initialization error: %d\n",
419 bt_plugin_get_name(plugin), status);
420 goto end;
421 }
422 }
423
424 spec->shared_lib_handle->init_called = true;
425
426 /* Add described component classes to plugin */
427 for (i = 0; i < comp_class_full_descriptors->len; i++) {
428 struct comp_class_full_descriptor *cc_full_descr =
429 &g_array_index(comp_class_full_descriptors,
430 struct comp_class_full_descriptor, i);
431 struct bt_component_class *comp_class;
432
433 switch (cc_full_descr->descriptor->type) {
434 case BT_COMPONENT_CLASS_TYPE_SOURCE:
435 comp_class = bt_component_class_source_create(
436 cc_full_descr->descriptor->name,
437 cc_full_descr->descriptor->methods.source.notif_iter_get,
438 cc_full_descr->descriptor->methods.source.notif_iter_next);
439 break;
440 case BT_COMPONENT_CLASS_TYPE_FILTER:
441 comp_class = bt_component_class_filter_create(
442 cc_full_descr->descriptor->name,
443 cc_full_descr->descriptor->methods.source.notif_iter_get,
444 cc_full_descr->descriptor->methods.source.notif_iter_next);
445 break;
446 case BT_COMPONENT_CLASS_TYPE_SINK:
447 comp_class = bt_component_class_sink_create(
448 cc_full_descr->descriptor->name,
449 cc_full_descr->descriptor->methods.sink.consume);
450 break;
451 default:
452 printf_verbose("WARNING: Unknown component class type %d for component class %s in plugin %s\n",
453 cc_full_descr->descriptor->type,
454 cc_full_descr->descriptor->name,
455 descriptor->name);
456 continue;
457 }
458
459 if (!comp_class) {
460 status = BT_PLUGIN_STATUS_ERROR;
461 goto end;
462 }
463
464 if (cc_full_descr->description) {
465 ret = bt_component_class_set_description(comp_class,
466 cc_full_descr->description);
467 if (ret) {
468 status = BT_PLUGIN_STATUS_ERROR;
469 BT_PUT(comp_class);
470 goto end;
471 }
472 }
473
279b3f15
PP
474 if (cc_full_descr->help) {
475 ret = bt_component_class_set_help(comp_class,
476 cc_full_descr->help);
477 if (ret) {
478 status = BT_PLUGIN_STATUS_ERROR;
479 BT_PUT(comp_class);
480 goto end;
481 }
482 }
483
55bb57e0
PP
484 if (cc_full_descr->init_method) {
485 ret = bt_component_class_set_init_method(comp_class,
486 cc_full_descr->init_method);
487 if (ret) {
488 status = BT_PLUGIN_STATUS_ERROR;
489 BT_PUT(comp_class);
490 goto end;
491 }
492 }
493
494 if (cc_full_descr->destroy_method) {
495 ret = bt_component_class_set_destroy_method(comp_class,
496 cc_full_descr->destroy_method);
497 if (ret) {
498 status = BT_PLUGIN_STATUS_ERROR;
499 BT_PUT(comp_class);
500 goto end;
501 }
502 }
503
a67681c1
PP
504 if (cc_full_descr->query_method) {
505 ret = bt_component_class_set_query_method(
506 comp_class, cc_full_descr->query_method);
8463eac2
PP
507 if (ret) {
508 status = BT_PLUGIN_STATUS_ERROR;
509 BT_PUT(comp_class);
510 goto end;
511 }
512 }
513
2d41b99e
JG
514 if (cc_full_descr->new_connection_method) {
515 ret = bt_component_class_set_new_connection_method(
516 comp_class, cc_full_descr->new_connection_method);
517 if (ret) {
518 status = BT_PLUGIN_STATUS_ERROR;
519 BT_PUT(comp_class);
520 goto end;
521 }
522 }
523
55bb57e0
PP
524 switch (cc_full_descr->descriptor->type) {
525 case BT_COMPONENT_CLASS_TYPE_SOURCE:
526 if (cc_full_descr->iterator_methods.init) {
527 ret = bt_component_class_source_set_notification_iterator_init_method(
528 comp_class,
529 cc_full_descr->iterator_methods.init);
530 if (ret) {
531 status = BT_PLUGIN_STATUS_ERROR;
532 BT_PUT(comp_class);
533 goto end;
534 }
535 }
536
537 if (cc_full_descr->iterator_methods.destroy) {
538 ret = bt_component_class_source_set_notification_iterator_destroy_method(
539 comp_class,
540 cc_full_descr->iterator_methods.destroy);
541 if (ret) {
542 status = BT_PLUGIN_STATUS_ERROR;
543 BT_PUT(comp_class);
544 goto end;
545 }
546 }
547
548 if (cc_full_descr->iterator_methods.seek_time) {
549 ret = bt_component_class_source_set_notification_iterator_seek_time_method(
550 comp_class,
551 cc_full_descr->iterator_methods.seek_time);
552 if (ret) {
553 status = BT_PLUGIN_STATUS_ERROR;
554 BT_PUT(comp_class);
555 goto end;
556 }
557 }
558 break;
559 case BT_COMPONENT_CLASS_TYPE_FILTER:
55bb57e0
PP
560 if (cc_full_descr->iterator_methods.init) {
561 ret = bt_component_class_filter_set_notification_iterator_init_method(
562 comp_class,
563 cc_full_descr->iterator_methods.init);
564 if (ret) {
565 status = BT_PLUGIN_STATUS_ERROR;
566 BT_PUT(comp_class);
567 goto end;
568 }
569 }
570
571 if (cc_full_descr->iterator_methods.destroy) {
572 ret = bt_component_class_filter_set_notification_iterator_destroy_method(
573 comp_class,
574 cc_full_descr->iterator_methods.destroy);
575 if (ret) {
576 status = BT_PLUGIN_STATUS_ERROR;
577 BT_PUT(comp_class);
578 goto end;
579 }
580 }
581
582 if (cc_full_descr->iterator_methods.seek_time) {
583 ret = bt_component_class_filter_set_notification_iterator_seek_time_method(
584 comp_class,
585 cc_full_descr->iterator_methods.seek_time);
586 if (ret) {
587 status = BT_PLUGIN_STATUS_ERROR;
588 BT_PUT(comp_class);
589 goto end;
590 }
591 }
592 break;
593 case BT_COMPONENT_CLASS_TYPE_SINK:
55bb57e0
PP
594 break;
595 default:
596 assert(false);
597 break;
598 }
599
600 /*
601 * Add component class to the plugin object.
602 *
603 * This will call back
604 * bt_plugin_so_on_add_component_class() so that we can
605 * add a mapping in comp_classes_to_shlib_handles when
606 * we know the component class is successfully added.
607 */
608 status = bt_plugin_add_component_class(plugin,
609 comp_class);
610 BT_PUT(comp_class);
611 if (status < 0) {
612 printf_verbose("Cannot add component class %s (type %d) to plugin `%s`: status = %d\n",
613 cc_full_descr->descriptor->name,
614 cc_full_descr->descriptor->type,
615 bt_plugin_get_name(plugin), status);
616 goto end;
617 }
618 }
619
620 /*
621 * All the plugin's component classes should be added at this
622 * point. We freeze the plugin so that it's not possible to add
623 * component classes to this plugin object after this stage
624 * (plugin object becomes immutable).
625 */
626 bt_plugin_freeze(plugin);
627
628end:
629 g_array_free(comp_class_full_descriptors, TRUE);
630 return status;
631}
632
633static
634struct bt_plugin *bt_plugin_so_create_empty(
635 struct bt_plugin_so_shared_lib_handle *shared_lib_handle)
636{
637 struct bt_plugin *plugin;
638 struct bt_plugin_so_spec_data *spec;
639
640 plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_SO);
641 if (!plugin) {
642 goto error;
643 }
644
645 plugin->spec_data = g_new0(struct bt_plugin_so_spec_data, 1);
646 if (!plugin->spec_data) {
647 goto error;
648 }
649
650 spec = plugin->spec_data;
651 spec->shared_lib_handle = bt_get(shared_lib_handle);
652 goto end;
653
654error:
655 BT_PUT(plugin);
656
657end:
658 return plugin;
659}
660
661static
662struct bt_plugin **bt_plugin_so_create_all_from_sections(
663 struct bt_plugin_so_shared_lib_handle *shared_lib_handle,
664 struct __bt_plugin_descriptor const * const *descriptors_begin,
665 struct __bt_plugin_descriptor const * const *descriptors_end,
666 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
667 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
668 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
669 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
670 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
671 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
672{
673 size_t descriptor_count;
674 size_t attrs_count;
675 size_t cc_descriptors_count;
676 size_t cc_descr_attrs_count;
677 size_t i;
678 struct bt_plugin **plugins = NULL;
679
680 descriptor_count = descriptors_end - descriptors_begin;
681 attrs_count = attrs_end - attrs_begin;
682 cc_descriptors_count = cc_descriptors_end - cc_descriptors_begin;
683 cc_descr_attrs_count = cc_descr_attrs_end - cc_descr_attrs_begin;
684 printf_verbose("Section: Plugin descriptors: [%p - %p], (%zu elements)\n",
685 descriptors_begin, descriptors_end, descriptor_count);
686 printf_verbose("Section: Plugin descriptor attributes: [%p - %p], (%zu elements)\n",
687 attrs_begin, attrs_end, attrs_count);
688 printf_verbose("Section: Plugin component class descriptors: [%p - %p], (%zu elements)\n",
689 cc_descriptors_begin, cc_descriptors_end, cc_descriptors_count);
690 printf_verbose("Section: Plugin component class descriptor attributes: [%p - %p], (%zu elements)\n",
691 cc_descr_attrs_begin, cc_descr_attrs_end, cc_descr_attrs_count);
692 plugins = calloc(descriptor_count + 1, sizeof(*plugins));
693 if (!plugins) {
694 goto error;
695 }
696
697 for (i = 0; i < descriptor_count; i++) {
698 enum bt_plugin_status status;
699 const struct __bt_plugin_descriptor *descriptor =
700 descriptors_begin[i];
701 struct bt_plugin *plugin;
702
703 printf_verbose("Loading plugin %s (ABI %d.%d)\n", descriptor->name,
704 descriptor->major, descriptor->minor);
705
706 if (descriptor->major > __BT_PLUGIN_VERSION_MAJOR) {
707 printf_error("Unknown plugin's major version: %d\n",
708 descriptor->major);
709 goto error;
710 }
711
712 plugin = bt_plugin_so_create_empty(shared_lib_handle);
713 if (!plugin) {
714 printf_error("Cannot allocate plugin object for plugin %s\n",
715 descriptor->name);
716 goto error;
717 }
718
719 if (shared_lib_handle && shared_lib_handle->path) {
720 bt_plugin_set_path(plugin, shared_lib_handle->path->str);
721 }
722
723 status = bt_plugin_so_init(plugin, descriptor, attrs_begin,
724 attrs_end, cc_descriptors_begin, cc_descriptors_end,
725 cc_descr_attrs_begin, cc_descr_attrs_end);
726 if (status < 0) {
727 printf_error("Cannot initialize plugin object %s\n",
728 descriptor->name);
729 BT_PUT(plugin);
730 goto error;
731 }
732
733 /* Transfer ownership to the array */
734 plugins[i] = plugin;
735 }
736
737 goto end;
738
739error:
740 g_free(plugins);
741 plugins = NULL;
742
743end:
744 return plugins;
745}
746
747BT_HIDDEN
748struct bt_plugin **bt_plugin_so_create_all_from_static(void)
749{
750 struct bt_plugin **plugins = NULL;
751 struct bt_plugin_so_shared_lib_handle *shared_lib_handle =
752 bt_plugin_so_shared_lib_handle_create(NULL);
753
754 if (!shared_lib_handle) {
755 goto end;
756 }
757
758 plugins = bt_plugin_so_create_all_from_sections(shared_lib_handle,
759 SECTION_BEGIN(__bt_plugin_descriptors),
760 SECTION_END(__bt_plugin_descriptors),
761 SECTION_BEGIN(__bt_plugin_descriptor_attributes),
762 SECTION_END(__bt_plugin_descriptor_attributes),
763 SECTION_BEGIN(__bt_plugin_component_class_descriptors),
764 SECTION_END(__bt_plugin_component_class_descriptors),
765 SECTION_BEGIN(__bt_plugin_component_class_descriptor_attributes),
766 SECTION_END(__bt_plugin_component_class_descriptor_attributes));
767
768end:
769 BT_PUT(shared_lib_handle);
770
771 return plugins;
772}
773
774BT_HIDDEN
775struct bt_plugin **bt_plugin_so_create_all_from_file(const char *path)
776{
777 size_t path_len;
778 struct bt_plugin **plugins = NULL;
779 struct __bt_plugin_descriptor const * const *descriptors_begin = NULL;
780 struct __bt_plugin_descriptor const * const *descriptors_end = NULL;
781 struct __bt_plugin_descriptor_attribute const * const *attrs_begin = NULL;
782 struct __bt_plugin_descriptor_attribute const * const *attrs_end = NULL;
783 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin = NULL;
784 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end = NULL;
785 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin = NULL;
786 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end = NULL;
787 bool is_libtool_wrapper = false, is_shared_object = false;
788 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
789
790 if (!path) {
791 goto end;
792 }
793
794 path_len = strlen(path);
795 if (path_len <= PLUGIN_SUFFIX_LEN) {
796 goto end;
797 }
798
799 path_len++;
800 /*
801 * Check if the file ends with a known plugin file type suffix (i.e. .so
802 * or .la on Linux).
803 */
804 is_libtool_wrapper = !strncmp(LIBTOOL_PLUGIN_SUFFIX,
805 path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN,
806 LIBTOOL_PLUGIN_SUFFIX_LEN);
807 is_shared_object = !strncmp(NATIVE_PLUGIN_SUFFIX,
808 path + path_len - NATIVE_PLUGIN_SUFFIX_LEN,
809 NATIVE_PLUGIN_SUFFIX_LEN);
810 if (!is_shared_object && !is_libtool_wrapper) {
811 /* Name indicates that this is not a plugin file. */
812 goto end;
813 }
814
815 shared_lib_handle = bt_plugin_so_shared_lib_handle_create(path);
816 if (!shared_lib_handle) {
817 goto end;
818 }
819
820 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_descriptors",
821 (gpointer *) &descriptors_begin)) {
822 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
823 "__start___bt_plugin_descriptors",
824 g_module_name(shared_lib_handle->module));
825 goto end;
826 }
827
828 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_descriptors",
829 (gpointer *) &descriptors_end)) {
830 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
831 "__stop___bt_plugin_descriptors",
832 g_module_name(shared_lib_handle->module));
833 goto end;
834 }
835
836 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_descriptor_attributes",
837 (gpointer *) &attrs_begin)) {
838 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
839 "__start___bt_plugin_descriptor_attributes",
840 g_module_name(shared_lib_handle->module));
841 }
842
843 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_descriptor_attributes",
844 (gpointer *) &attrs_end)) {
845 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
846 "__stop___bt_plugin_descriptor_attributes",
847 g_module_name(shared_lib_handle->module));
848 }
849
850 if ((!!attrs_begin - !!attrs_end) != 0) {
851 printf_verbose("Found __start___bt_plugin_descriptor_attributes or __stop___bt_plugin_descriptor_attributes symbol, but not both in %s\n",
852 g_module_name(shared_lib_handle->module));
853 goto end;
854 }
855
856 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_component_class_descriptors",
857 (gpointer *) &cc_descriptors_begin)) {
858 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
859 "__start___bt_plugin_component_class_descriptors",
860 g_module_name(shared_lib_handle->module));
861 }
862
863 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_component_class_descriptors",
864 (gpointer *) &cc_descriptors_end)) {
865 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
866 "__stop___bt_plugin_component_class_descriptors",
867 g_module_name(shared_lib_handle->module));
868 }
869
870 if ((!!cc_descriptors_begin - !!cc_descriptors_end) != 0) {
871 printf_verbose("Found __start___bt_plugin_component_class_descriptors or __stop___bt_plugin_component_class_descriptors symbol, but not both in %s\n",
872 g_module_name(shared_lib_handle->module));
873 goto end;
874 }
875
876 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_component_class_descriptor_attributes",
877 (gpointer *) &cc_descr_attrs_begin)) {
878 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
879 "__start___bt_plugin_component_class_descriptor_attributes",
880 g_module_name(shared_lib_handle->module));
881 }
882
883 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_component_class_descriptor_attributes",
884 (gpointer *) &cc_descr_attrs_end)) {
885 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
886 "__stop___bt_plugin_component_class_descriptor_attributes",
887 g_module_name(shared_lib_handle->module));
888 }
889
890 if ((!!cc_descr_attrs_begin - !!cc_descr_attrs_end) != 0) {
891 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",
892 g_module_name(shared_lib_handle->module));
893 goto end;
894 }
895
896 /* Initialize plugin */
897 plugins = bt_plugin_so_create_all_from_sections(shared_lib_handle,
898 descriptors_begin, descriptors_end, attrs_begin, attrs_end,
899 cc_descriptors_begin, cc_descriptors_end,
900 cc_descr_attrs_begin, cc_descr_attrs_end);
901
902end:
903 BT_PUT(shared_lib_handle);
904 return plugins;
905}
906
907static
908void plugin_comp_class_destroy_listener(struct bt_component_class *comp_class,
909 void *data)
910{
911 gboolean exists = g_hash_table_remove(comp_classes_to_shlib_handles,
912 comp_class);
913 assert(exists);
914}
915
916BT_HIDDEN
917int bt_plugin_so_on_add_component_class(struct bt_plugin *plugin,
918 struct bt_component_class *comp_class)
919{
920 int ret;
921 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
922
923 assert(plugin->spec_data);
924 assert(plugin->type == BT_PLUGIN_TYPE_SO);
925
926 /* Map component class pointer to shared lib handle in global HT */
927 g_hash_table_insert(comp_classes_to_shlib_handles, comp_class,
928 bt_get(spec->shared_lib_handle));
929
930 /* Add our custom destroy listener */
931 ret = bt_component_class_add_destroy_listener(comp_class,
932 plugin_comp_class_destroy_listener, NULL);
933 if (ret) {
934 goto error;
935 }
936 goto end;
937
938error:
939 /* Remove entry from global hash table (if exists) */
940 g_hash_table_remove(comp_classes_to_shlib_handles,
941 comp_class);
942
943end:
944 return ret;
945}
This page took 0.057041 seconds and 4 git commands to generate.