lib/graph/iterator.c: add logging
[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>
c55a9f58 37#include <babeltrace/types.h>
55bb57e0 38#include <string.h>
55bb57e0
PP
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) {
f1447220
PP
141#ifndef NDEBUG
142 /*
143 * Valgrind shows incomplete stack traces when
144 * dynamically loaded libraries are closed before it
145 * finishes. Use the BABELTRACE_NO_DLCLOSE in a debug
146 * build to avoid this.
147 */
148 const char *var = getenv("BABELTRACE_NO_DLCLOSE");
149
150 if (!var || strcmp(var, "1") != 0) {
151#endif
152 if (!g_module_close(shared_lib_handle->module)) {
153 printf_error("Module close error: %s\n",
154 g_module_error());
155 }
156#ifndef NDEBUG
55bb57e0 157 }
f1447220 158#endif
55bb57e0
PP
159 }
160
161 if (shared_lib_handle->path) {
162 g_string_free(shared_lib_handle->path, TRUE);
163 }
164
165 g_free(shared_lib_handle);
166}
167
168static
169struct bt_plugin_so_shared_lib_handle *bt_plugin_so_shared_lib_handle_create(
170 const char *path)
171{
172 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
173
174 shared_lib_handle = g_new0(struct bt_plugin_so_shared_lib_handle, 1);
175 if (!shared_lib_handle) {
176 goto error;
177 }
178
179 bt_object_init(shared_lib_handle, bt_plugin_so_shared_lib_handle_destroy);
180
181 if (!path) {
182 goto end;
183 }
184
185 shared_lib_handle->path = g_string_new(path);
186 if (!shared_lib_handle->path) {
187 goto error;
188 }
189
190 shared_lib_handle->module = g_module_open(path, 0);
191 if (!shared_lib_handle->module) {
192 printf_verbose("Module open error: %s\n", g_module_error());
193 goto error;
194 }
195
196 goto end;
197
198error:
199 BT_PUT(shared_lib_handle);
200
201end:
202 return shared_lib_handle;
203}
204
6fbd4105 205static
55bb57e0
PP
206void bt_plugin_so_destroy_spec_data(struct bt_plugin *plugin)
207{
208 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
209
210 if (!plugin->spec_data) {
211 return;
212 }
213
214 assert(plugin->type == BT_PLUGIN_TYPE_SO);
215 assert(spec);
216 BT_PUT(spec->shared_lib_handle);
217 g_free(plugin->spec_data);
218 plugin->spec_data = NULL;
219}
220
221/*
222 * This function does the following:
223 *
224 * 1. Iterate on the plugin descriptor attributes section and set the
225 * plugin's attributes depending on the attribute types. This
226 * includes the name of the plugin, its description, and its
227 * initialization function, for example.
228 *
229 * 2. Iterate on the component class descriptors section and create one
230 * "full descriptor" (temporary structure) for each one that is found
231 * and attached to our plugin descriptor.
232 *
233 * 3. Iterate on the component class descriptor attributes section and
234 * set the corresponding full descriptor's attributes depending on
235 * the attribute types. This includes the description of the
236 * component class, as well as its initialization and destroy
237 * methods.
238 *
239 * 4. Call the user's plugin initialization function, if any is
240 * defined.
241 *
242 * 5. For each full component class descriptor, create a component class
243 * object, set its optional attributes, and add it to the plugin
244 * object.
245 *
246 * 6. Freeze the plugin object.
247 */
248static
249enum bt_plugin_status bt_plugin_so_init(
250 struct bt_plugin *plugin,
251 const struct __bt_plugin_descriptor *descriptor,
252 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
253 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
254 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
255 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
256 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
257 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
258{
259 /*
260 * This structure's members point to the plugin's memory
261 * (do NOT free).
262 */
263 struct comp_class_full_descriptor {
264 const struct __bt_plugin_component_class_descriptor *descriptor;
265 const char *description;
279b3f15 266 const char *help;
55bb57e0 267 bt_component_class_init_method init_method;
64cadc66 268 bt_component_class_finalize_method finalize_method;
a67681c1 269 bt_component_class_query_method query_method;
72b913fb 270 bt_component_class_accept_port_connection_method accept_port_connection_method;
0d8b4d8e 271 bt_component_class_port_connected_method port_connected_method;
72b913fb 272 bt_component_class_port_disconnected_method port_disconnected_method;
55bb57e0
PP
273 struct bt_component_class_iterator_methods iterator_methods;
274 };
275
276 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
277 struct __bt_plugin_descriptor_attribute const * const *cur_attr_ptr;
278 struct __bt_plugin_component_class_descriptor const * const *cur_cc_descr_ptr;
279 struct __bt_plugin_component_class_descriptor_attribute const * const *cur_cc_descr_attr_ptr;
280 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
281 GArray *comp_class_full_descriptors;
282 size_t i;
283 int ret;
284
285 comp_class_full_descriptors = g_array_new(FALSE, TRUE,
286 sizeof(struct comp_class_full_descriptor));
287 if (!comp_class_full_descriptors) {
288 status = BT_PLUGIN_STATUS_ERROR;
289 goto end;
290 }
291
292 /* Set mandatory attributes */
293 spec->descriptor = descriptor;
294 bt_plugin_set_name(plugin, descriptor->name);
295
296 /*
297 * Find and set optional attributes attached to this plugin
298 * descriptor.
299 */
300 for (cur_attr_ptr = attrs_begin; cur_attr_ptr != attrs_end; cur_attr_ptr++) {
301 const struct __bt_plugin_descriptor_attribute *cur_attr =
302 *cur_attr_ptr;
303
304 if (cur_attr->plugin_descriptor != descriptor) {
305 continue;
306 }
307
308 switch (cur_attr->type) {
309 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT:
310 spec->init = cur_attr->value.init;
311 break;
312 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT:
313 spec->shared_lib_handle->exit = cur_attr->value.exit;
314 break;
315 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR:
316 bt_plugin_set_author(plugin, cur_attr->value.author);
317 break;
318 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE:
319 bt_plugin_set_license(plugin, cur_attr->value.license);
320 break;
321 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
322 bt_plugin_set_description(plugin, cur_attr->value.description);
323 break;
324 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION:
325 bt_plugin_set_version(plugin,
326 (unsigned int) cur_attr->value.version.major,
327 (unsigned int) cur_attr->value.version.minor,
328 (unsigned int) cur_attr->value.version.patch,
329 cur_attr->value.version.extra);
330 break;
331 default:
332 printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for plugin %s\n",
333 cur_attr->type_name, cur_attr->type,
334 descriptor->name);
335 break;
336 }
337 }
338
339 /*
340 * Find component class descriptors attached to this plugin
341 * descriptor and initialize corresponding full component class
342 * descriptors in the array.
343 */
344 for (cur_cc_descr_ptr = cc_descriptors_begin; cur_cc_descr_ptr != cc_descriptors_end; cur_cc_descr_ptr++) {
345 const struct __bt_plugin_component_class_descriptor *cur_cc_descr =
346 *cur_cc_descr_ptr;
347 struct comp_class_full_descriptor full_descriptor = {0};
348
349 if (cur_cc_descr->plugin_descriptor != descriptor) {
350 continue;
351 }
352
353 full_descriptor.descriptor = cur_cc_descr;
354 g_array_append_val(comp_class_full_descriptors,
355 full_descriptor);
356 }
357
358 /*
359 * Find component class descriptor attributes attached to this
360 * plugin descriptor and update corresponding full component
361 * class descriptors in the array.
362 */
363 for (cur_cc_descr_attr_ptr = cc_descr_attrs_begin; cur_cc_descr_attr_ptr != cc_descr_attrs_end; cur_cc_descr_attr_ptr++) {
364 const struct __bt_plugin_component_class_descriptor_attribute *cur_cc_descr_attr =
365 *cur_cc_descr_attr_ptr;
366
367 if (cur_cc_descr_attr->comp_class_descriptor->plugin_descriptor !=
368 descriptor) {
369 continue;
370 }
371
372 /* Find the corresponding component class descriptor entry */
373 for (i = 0; i < comp_class_full_descriptors->len; i++) {
374 struct comp_class_full_descriptor *cc_full_descr =
375 &g_array_index(comp_class_full_descriptors,
376 struct comp_class_full_descriptor, i);
377
378 if (cur_cc_descr_attr->comp_class_descriptor ==
379 cc_full_descr->descriptor) {
380 switch (cur_cc_descr_attr->type) {
381 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
382 cc_full_descr->description =
383 cur_cc_descr_attr->value.description;
384 break;
279b3f15
PP
385 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP:
386 cc_full_descr->help =
387 cur_cc_descr_attr->value.help;
388 break;
55bb57e0
PP
389 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INIT_METHOD:
390 cc_full_descr->init_method =
391 cur_cc_descr_attr->value.init_method;
392 break;
64cadc66
PP
393 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD:
394 cc_full_descr->finalize_method =
395 cur_cc_descr_attr->value.finalize_method;
55bb57e0 396 break;
a67681c1
PP
397 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD:
398 cc_full_descr->query_method =
399 cur_cc_descr_attr->value.query_method;
8463eac2 400 break;
72b913fb
PP
401 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_ACCEPT_PORT_CONNECTION_METHOD:
402 cc_full_descr->accept_port_connection_method =
403 cur_cc_descr_attr->value.accept_port_connection_method;
404 break;
0d8b4d8e
PP
405 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD:
406 cc_full_descr->port_connected_method =
407 cur_cc_descr_attr->value.port_connected_method;
408 break;
72b913fb
PP
409 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_DISCONNECTED_METHOD:
410 cc_full_descr->port_disconnected_method =
411 cur_cc_descr_attr->value.port_disconnected_method;
55bb57e0
PP
412 break;
413 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_INIT_METHOD:
414 cc_full_descr->iterator_methods.init =
415 cur_cc_descr_attr->value.notif_iter_init_method;
416 break;
64cadc66
PP
417 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_FINALIZE_METHOD:
418 cc_full_descr->iterator_methods.finalize =
419 cur_cc_descr_attr->value.notif_iter_finalize_method;
55bb57e0
PP
420 break;
421 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_SEEK_TIME_METHOD:
422 cc_full_descr->iterator_methods.seek_time =
423 cur_cc_descr_attr->value.notif_iter_seek_time_method;
424 break;
425 default:
426 printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for component class %s (type %d) in plugin %s\n",
427 cur_cc_descr_attr->type_name,
428 cur_cc_descr_attr->type,
429 cur_cc_descr_attr->comp_class_descriptor->name,
430 cur_cc_descr_attr->comp_class_descriptor->type,
431 descriptor->name);
432 break;
433 }
434 }
435 }
436 }
437
438 /* Initialize plugin */
439 if (spec->init) {
440 status = spec->init(plugin);
441 if (status < 0) {
442 printf_verbose("Plugin `%s` initialization error: %d\n",
443 bt_plugin_get_name(plugin), status);
444 goto end;
445 }
446 }
447
c55a9f58 448 spec->shared_lib_handle->init_called = BT_TRUE;
55bb57e0
PP
449
450 /* Add described component classes to plugin */
451 for (i = 0; i < comp_class_full_descriptors->len; i++) {
452 struct comp_class_full_descriptor *cc_full_descr =
453 &g_array_index(comp_class_full_descriptors,
454 struct comp_class_full_descriptor, i);
455 struct bt_component_class *comp_class;
456
457 switch (cc_full_descr->descriptor->type) {
458 case BT_COMPONENT_CLASS_TYPE_SOURCE:
459 comp_class = bt_component_class_source_create(
460 cc_full_descr->descriptor->name,
55bb57e0
PP
461 cc_full_descr->descriptor->methods.source.notif_iter_next);
462 break;
463 case BT_COMPONENT_CLASS_TYPE_FILTER:
464 comp_class = bt_component_class_filter_create(
465 cc_full_descr->descriptor->name,
55bb57e0
PP
466 cc_full_descr->descriptor->methods.source.notif_iter_next);
467 break;
468 case BT_COMPONENT_CLASS_TYPE_SINK:
469 comp_class = bt_component_class_sink_create(
470 cc_full_descr->descriptor->name,
471 cc_full_descr->descriptor->methods.sink.consume);
472 break;
473 default:
474 printf_verbose("WARNING: Unknown component class type %d for component class %s in plugin %s\n",
475 cc_full_descr->descriptor->type,
476 cc_full_descr->descriptor->name,
477 descriptor->name);
478 continue;
479 }
480
481 if (!comp_class) {
482 status = BT_PLUGIN_STATUS_ERROR;
483 goto end;
484 }
485
486 if (cc_full_descr->description) {
487 ret = bt_component_class_set_description(comp_class,
488 cc_full_descr->description);
489 if (ret) {
490 status = BT_PLUGIN_STATUS_ERROR;
491 BT_PUT(comp_class);
492 goto end;
493 }
494 }
495
279b3f15
PP
496 if (cc_full_descr->help) {
497 ret = bt_component_class_set_help(comp_class,
498 cc_full_descr->help);
499 if (ret) {
500 status = BT_PLUGIN_STATUS_ERROR;
501 BT_PUT(comp_class);
502 goto end;
503 }
504 }
505
55bb57e0
PP
506 if (cc_full_descr->init_method) {
507 ret = bt_component_class_set_init_method(comp_class,
508 cc_full_descr->init_method);
509 if (ret) {
510 status = BT_PLUGIN_STATUS_ERROR;
511 BT_PUT(comp_class);
512 goto end;
513 }
514 }
515
64cadc66
PP
516 if (cc_full_descr->finalize_method) {
517 ret = bt_component_class_set_finalize_method(comp_class,
518 cc_full_descr->finalize_method);
55bb57e0
PP
519 if (ret) {
520 status = BT_PLUGIN_STATUS_ERROR;
521 BT_PUT(comp_class);
522 goto end;
523 }
524 }
525
a67681c1
PP
526 if (cc_full_descr->query_method) {
527 ret = bt_component_class_set_query_method(
528 comp_class, cc_full_descr->query_method);
8463eac2
PP
529 if (ret) {
530 status = BT_PLUGIN_STATUS_ERROR;
531 BT_PUT(comp_class);
532 goto end;
533 }
534 }
535
72b913fb
PP
536 if (cc_full_descr->accept_port_connection_method) {
537 ret = bt_component_class_set_accept_port_connection_method(
538 comp_class, cc_full_descr->accept_port_connection_method);
539 if (ret) {
540 status = BT_PLUGIN_STATUS_ERROR;
541 BT_PUT(comp_class);
542 goto end;
543 }
544 }
545
0d8b4d8e
PP
546 if (cc_full_descr->port_connected_method) {
547 ret = bt_component_class_set_port_connected_method(
548 comp_class, cc_full_descr->port_connected_method);
549 if (ret) {
550 status = BT_PLUGIN_STATUS_ERROR;
551 BT_PUT(comp_class);
552 goto end;
553 }
554 }
555
72b913fb
PP
556 if (cc_full_descr->port_disconnected_method) {
557 ret = bt_component_class_set_port_disconnected_method(
558 comp_class, cc_full_descr->port_disconnected_method);
2d41b99e
JG
559 if (ret) {
560 status = BT_PLUGIN_STATUS_ERROR;
561 BT_PUT(comp_class);
562 goto end;
563 }
564 }
565
55bb57e0
PP
566 switch (cc_full_descr->descriptor->type) {
567 case BT_COMPONENT_CLASS_TYPE_SOURCE:
568 if (cc_full_descr->iterator_methods.init) {
569 ret = bt_component_class_source_set_notification_iterator_init_method(
570 comp_class,
571 cc_full_descr->iterator_methods.init);
572 if (ret) {
573 status = BT_PLUGIN_STATUS_ERROR;
574 BT_PUT(comp_class);
575 goto end;
576 }
577 }
578
64cadc66
PP
579 if (cc_full_descr->iterator_methods.finalize) {
580 ret = bt_component_class_source_set_notification_iterator_finalize_method(
55bb57e0 581 comp_class,
64cadc66 582 cc_full_descr->iterator_methods.finalize);
55bb57e0
PP
583 if (ret) {
584 status = BT_PLUGIN_STATUS_ERROR;
585 BT_PUT(comp_class);
586 goto end;
587 }
588 }
589
590 if (cc_full_descr->iterator_methods.seek_time) {
591 ret = bt_component_class_source_set_notification_iterator_seek_time_method(
592 comp_class,
593 cc_full_descr->iterator_methods.seek_time);
594 if (ret) {
595 status = BT_PLUGIN_STATUS_ERROR;
596 BT_PUT(comp_class);
597 goto end;
598 }
599 }
600 break;
601 case BT_COMPONENT_CLASS_TYPE_FILTER:
55bb57e0
PP
602 if (cc_full_descr->iterator_methods.init) {
603 ret = bt_component_class_filter_set_notification_iterator_init_method(
604 comp_class,
605 cc_full_descr->iterator_methods.init);
606 if (ret) {
607 status = BT_PLUGIN_STATUS_ERROR;
608 BT_PUT(comp_class);
609 goto end;
610 }
611 }
612
64cadc66
PP
613 if (cc_full_descr->iterator_methods.finalize) {
614 ret = bt_component_class_filter_set_notification_iterator_finalize_method(
55bb57e0 615 comp_class,
64cadc66 616 cc_full_descr->iterator_methods.finalize);
55bb57e0
PP
617 if (ret) {
618 status = BT_PLUGIN_STATUS_ERROR;
619 BT_PUT(comp_class);
620 goto end;
621 }
622 }
623
624 if (cc_full_descr->iterator_methods.seek_time) {
625 ret = bt_component_class_filter_set_notification_iterator_seek_time_method(
626 comp_class,
627 cc_full_descr->iterator_methods.seek_time);
628 if (ret) {
629 status = BT_PLUGIN_STATUS_ERROR;
630 BT_PUT(comp_class);
631 goto end;
632 }
633 }
634 break;
635 case BT_COMPONENT_CLASS_TYPE_SINK:
55bb57e0
PP
636 break;
637 default:
c55a9f58 638 assert(BT_FALSE);
55bb57e0
PP
639 break;
640 }
641
642 /*
643 * Add component class to the plugin object.
644 *
645 * This will call back
646 * bt_plugin_so_on_add_component_class() so that we can
647 * add a mapping in comp_classes_to_shlib_handles when
648 * we know the component class is successfully added.
649 */
650 status = bt_plugin_add_component_class(plugin,
651 comp_class);
652 BT_PUT(comp_class);
653 if (status < 0) {
654 printf_verbose("Cannot add component class %s (type %d) to plugin `%s`: status = %d\n",
655 cc_full_descr->descriptor->name,
656 cc_full_descr->descriptor->type,
657 bt_plugin_get_name(plugin), status);
658 goto end;
659 }
660 }
661
662 /*
663 * All the plugin's component classes should be added at this
664 * point. We freeze the plugin so that it's not possible to add
665 * component classes to this plugin object after this stage
666 * (plugin object becomes immutable).
667 */
668 bt_plugin_freeze(plugin);
669
670end:
671 g_array_free(comp_class_full_descriptors, TRUE);
672 return status;
673}
674
675static
676struct bt_plugin *bt_plugin_so_create_empty(
677 struct bt_plugin_so_shared_lib_handle *shared_lib_handle)
678{
679 struct bt_plugin *plugin;
680 struct bt_plugin_so_spec_data *spec;
681
682 plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_SO);
683 if (!plugin) {
684 goto error;
685 }
686
6fbd4105 687 plugin->destroy_spec_data = bt_plugin_so_destroy_spec_data;
55bb57e0
PP
688 plugin->spec_data = g_new0(struct bt_plugin_so_spec_data, 1);
689 if (!plugin->spec_data) {
690 goto error;
691 }
692
693 spec = plugin->spec_data;
694 spec->shared_lib_handle = bt_get(shared_lib_handle);
695 goto end;
696
697error:
698 BT_PUT(plugin);
699
700end:
701 return plugin;
702}
703
704static
a8ff38ef 705struct bt_plugin_set *bt_plugin_so_create_all_from_sections(
55bb57e0
PP
706 struct bt_plugin_so_shared_lib_handle *shared_lib_handle,
707 struct __bt_plugin_descriptor const * const *descriptors_begin,
708 struct __bt_plugin_descriptor const * const *descriptors_end,
709 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
710 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
711 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
712 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
713 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
714 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
715{
716 size_t descriptor_count;
717 size_t attrs_count;
718 size_t cc_descriptors_count;
719 size_t cc_descr_attrs_count;
720 size_t i;
a8ff38ef 721 struct bt_plugin_set *plugin_set = NULL;
55bb57e0
PP
722
723 descriptor_count = descriptors_end - descriptors_begin;
724 attrs_count = attrs_end - attrs_begin;
725 cc_descriptors_count = cc_descriptors_end - cc_descriptors_begin;
726 cc_descr_attrs_count = cc_descr_attrs_end - cc_descr_attrs_begin;
727 printf_verbose("Section: Plugin descriptors: [%p - %p], (%zu elements)\n",
728 descriptors_begin, descriptors_end, descriptor_count);
729 printf_verbose("Section: Plugin descriptor attributes: [%p - %p], (%zu elements)\n",
730 attrs_begin, attrs_end, attrs_count);
731 printf_verbose("Section: Plugin component class descriptors: [%p - %p], (%zu elements)\n",
732 cc_descriptors_begin, cc_descriptors_end, cc_descriptors_count);
733 printf_verbose("Section: Plugin component class descriptor attributes: [%p - %p], (%zu elements)\n",
734 cc_descr_attrs_begin, cc_descr_attrs_end, cc_descr_attrs_count);
a8ff38ef
PP
735 plugin_set = bt_plugin_set_create();
736 if (!plugin_set) {
55bb57e0
PP
737 goto error;
738 }
739
740 for (i = 0; i < descriptor_count; i++) {
741 enum bt_plugin_status status;
742 const struct __bt_plugin_descriptor *descriptor =
743 descriptors_begin[i];
744 struct bt_plugin *plugin;
745
746 printf_verbose("Loading plugin %s (ABI %d.%d)\n", descriptor->name,
747 descriptor->major, descriptor->minor);
748
749 if (descriptor->major > __BT_PLUGIN_VERSION_MAJOR) {
750 printf_error("Unknown plugin's major version: %d\n",
751 descriptor->major);
752 goto error;
753 }
754
755 plugin = bt_plugin_so_create_empty(shared_lib_handle);
756 if (!plugin) {
757 printf_error("Cannot allocate plugin object for plugin %s\n",
758 descriptor->name);
759 goto error;
760 }
761
762 if (shared_lib_handle && shared_lib_handle->path) {
763 bt_plugin_set_path(plugin, shared_lib_handle->path->str);
764 }
765
766 status = bt_plugin_so_init(plugin, descriptor, attrs_begin,
767 attrs_end, cc_descriptors_begin, cc_descriptors_end,
768 cc_descr_attrs_begin, cc_descr_attrs_end);
769 if (status < 0) {
770 printf_error("Cannot initialize plugin object %s\n",
771 descriptor->name);
772 BT_PUT(plugin);
773 goto error;
774 }
775
a8ff38ef
PP
776 /* Add to plugin set */
777 bt_plugin_set_add_plugin(plugin_set, plugin);
778 bt_put(plugin);
55bb57e0
PP
779 }
780
781 goto end;
782
783error:
a8ff38ef 784 BT_PUT(plugin_set);
55bb57e0
PP
785
786end:
a8ff38ef 787 return plugin_set;
55bb57e0
PP
788}
789
790BT_HIDDEN
a8ff38ef 791struct bt_plugin_set *bt_plugin_so_create_all_from_static(void)
55bb57e0 792{
a8ff38ef 793 struct bt_plugin_set *plugin_set = NULL;
55bb57e0
PP
794 struct bt_plugin_so_shared_lib_handle *shared_lib_handle =
795 bt_plugin_so_shared_lib_handle_create(NULL);
796
797 if (!shared_lib_handle) {
798 goto end;
799 }
800
a8ff38ef 801 plugin_set = bt_plugin_so_create_all_from_sections(shared_lib_handle,
55bb57e0
PP
802 SECTION_BEGIN(__bt_plugin_descriptors),
803 SECTION_END(__bt_plugin_descriptors),
804 SECTION_BEGIN(__bt_plugin_descriptor_attributes),
805 SECTION_END(__bt_plugin_descriptor_attributes),
806 SECTION_BEGIN(__bt_plugin_component_class_descriptors),
807 SECTION_END(__bt_plugin_component_class_descriptors),
808 SECTION_BEGIN(__bt_plugin_component_class_descriptor_attributes),
809 SECTION_END(__bt_plugin_component_class_descriptor_attributes));
810
811end:
812 BT_PUT(shared_lib_handle);
813
a8ff38ef 814 return plugin_set;
55bb57e0
PP
815}
816
817BT_HIDDEN
a8ff38ef 818struct bt_plugin_set *bt_plugin_so_create_all_from_file(const char *path)
55bb57e0
PP
819{
820 size_t path_len;
a8ff38ef 821 struct bt_plugin_set *plugin_set = NULL;
55bb57e0
PP
822 struct __bt_plugin_descriptor const * const *descriptors_begin = NULL;
823 struct __bt_plugin_descriptor const * const *descriptors_end = NULL;
824 struct __bt_plugin_descriptor_attribute const * const *attrs_begin = NULL;
825 struct __bt_plugin_descriptor_attribute const * const *attrs_end = NULL;
826 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin = NULL;
827 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end = NULL;
828 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin = NULL;
829 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end = NULL;
c55a9f58 830 bt_bool is_libtool_wrapper = BT_FALSE, is_shared_object = BT_FALSE;
55bb57e0
PP
831 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
832
833 if (!path) {
834 goto end;
835 }
836
837 path_len = strlen(path);
838 if (path_len <= PLUGIN_SUFFIX_LEN) {
839 goto end;
840 }
841
842 path_len++;
843 /*
844 * Check if the file ends with a known plugin file type suffix (i.e. .so
845 * or .la on Linux).
846 */
847 is_libtool_wrapper = !strncmp(LIBTOOL_PLUGIN_SUFFIX,
848 path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN,
849 LIBTOOL_PLUGIN_SUFFIX_LEN);
850 is_shared_object = !strncmp(NATIVE_PLUGIN_SUFFIX,
851 path + path_len - NATIVE_PLUGIN_SUFFIX_LEN,
852 NATIVE_PLUGIN_SUFFIX_LEN);
853 if (!is_shared_object && !is_libtool_wrapper) {
854 /* Name indicates that this is not a plugin file. */
855 goto end;
856 }
857
858 shared_lib_handle = bt_plugin_so_shared_lib_handle_create(path);
859 if (!shared_lib_handle) {
860 goto end;
861 }
862
863 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_descriptors",
864 (gpointer *) &descriptors_begin)) {
865 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
866 "__start___bt_plugin_descriptors",
867 g_module_name(shared_lib_handle->module));
868 goto end;
869 }
870
871 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_descriptors",
872 (gpointer *) &descriptors_end)) {
873 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
874 "__stop___bt_plugin_descriptors",
875 g_module_name(shared_lib_handle->module));
876 goto end;
877 }
878
879 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_descriptor_attributes",
880 (gpointer *) &attrs_begin)) {
881 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
882 "__start___bt_plugin_descriptor_attributes",
883 g_module_name(shared_lib_handle->module));
884 }
885
886 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_descriptor_attributes",
887 (gpointer *) &attrs_end)) {
888 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
889 "__stop___bt_plugin_descriptor_attributes",
890 g_module_name(shared_lib_handle->module));
891 }
892
893 if ((!!attrs_begin - !!attrs_end) != 0) {
894 printf_verbose("Found __start___bt_plugin_descriptor_attributes or __stop___bt_plugin_descriptor_attributes symbol, but not both in %s\n",
895 g_module_name(shared_lib_handle->module));
896 goto end;
897 }
898
899 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_component_class_descriptors",
900 (gpointer *) &cc_descriptors_begin)) {
901 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
902 "__start___bt_plugin_component_class_descriptors",
903 g_module_name(shared_lib_handle->module));
904 }
905
906 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_component_class_descriptors",
907 (gpointer *) &cc_descriptors_end)) {
908 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
909 "__stop___bt_plugin_component_class_descriptors",
910 g_module_name(shared_lib_handle->module));
911 }
912
913 if ((!!cc_descriptors_begin - !!cc_descriptors_end) != 0) {
914 printf_verbose("Found __start___bt_plugin_component_class_descriptors or __stop___bt_plugin_component_class_descriptors symbol, but not both in %s\n",
915 g_module_name(shared_lib_handle->module));
916 goto end;
917 }
918
919 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_component_class_descriptor_attributes",
920 (gpointer *) &cc_descr_attrs_begin)) {
921 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
922 "__start___bt_plugin_component_class_descriptor_attributes",
923 g_module_name(shared_lib_handle->module));
924 }
925
926 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_component_class_descriptor_attributes",
927 (gpointer *) &cc_descr_attrs_end)) {
928 printf_verbose("Unable to resolve plugin symbol %s from %s\n",
929 "__stop___bt_plugin_component_class_descriptor_attributes",
930 g_module_name(shared_lib_handle->module));
931 }
932
933 if ((!!cc_descr_attrs_begin - !!cc_descr_attrs_end) != 0) {
934 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",
935 g_module_name(shared_lib_handle->module));
936 goto end;
937 }
938
939 /* Initialize plugin */
a8ff38ef 940 plugin_set = bt_plugin_so_create_all_from_sections(shared_lib_handle,
55bb57e0
PP
941 descriptors_begin, descriptors_end, attrs_begin, attrs_end,
942 cc_descriptors_begin, cc_descriptors_end,
943 cc_descr_attrs_begin, cc_descr_attrs_end);
944
945end:
946 BT_PUT(shared_lib_handle);
a8ff38ef 947 return plugin_set;
55bb57e0
PP
948}
949
950static
951void plugin_comp_class_destroy_listener(struct bt_component_class *comp_class,
952 void *data)
953{
954 gboolean exists = g_hash_table_remove(comp_classes_to_shlib_handles,
955 comp_class);
956 assert(exists);
957}
958
959BT_HIDDEN
3230ee6b 960void bt_plugin_so_on_add_component_class(struct bt_plugin *plugin,
55bb57e0
PP
961 struct bt_component_class *comp_class)
962{
55bb57e0
PP
963 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
964
965 assert(plugin->spec_data);
966 assert(plugin->type == BT_PLUGIN_TYPE_SO);
967
968 /* Map component class pointer to shared lib handle in global HT */
969 g_hash_table_insert(comp_classes_to_shlib_handles, comp_class,
970 bt_get(spec->shared_lib_handle));
971
972 /* Add our custom destroy listener */
3230ee6b 973 bt_component_class_add_destroy_listener(comp_class,
55bb57e0 974 plugin_comp_class_destroy_listener, NULL);
55bb57e0 975}
This page took 0.063295 seconds and 4 git commands to generate.