test_ctf_writer.c: add "trace is static" listener 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
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>
0fbb9a9f 39#include <stdlib.h>
55bb57e0
PP
40#include <glib.h>
41#include <gmodule.h>
42
43#define NATIVE_PLUGIN_SUFFIX ".so"
44#define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
45#define LIBTOOL_PLUGIN_SUFFIX ".la"
46#define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
47
48#define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
49 sizeof(LIBTOOL_PLUGIN_SUFFIX))
50
51#define SECTION_BEGIN(_name) (&(__start_##_name))
52#define SECTION_END(_name) (&(__stop_##_name))
53#define SECTION_ELEMENT_COUNT(_name) (SECTION_END(_name) - SECTION_BEGIN(_name))
54
55#define DECLARE_SECTION(_type, _name) \
56 extern _type __start_##_name __attribute((weak)); \
57 extern _type __stop_##_name __attribute((weak))
58
59DECLARE_SECTION(struct __bt_plugin_descriptor const *, __bt_plugin_descriptors);
60DECLARE_SECTION(struct __bt_plugin_descriptor_attribute const *, __bt_plugin_descriptor_attributes);
61DECLARE_SECTION(struct __bt_plugin_component_class_descriptor const *, __bt_plugin_component_class_descriptors);
62DECLARE_SECTION(struct __bt_plugin_component_class_descriptor_attribute const *, __bt_plugin_component_class_descriptor_attributes);
63
64/*
65 * This hash table, global to the library, maps component class pointers
66 * to shared library handles.
67 *
68 * The keys (component classes) are NOT owned by this hash table, whereas
69 * the values (shared library handles) are owned by this hash table.
70 *
71 * The keys are the component classes created with
72 * bt_plugin_add_component_class(). They keep the shared library handle
73 * object created by their plugin alive so that the plugin's code is
74 * not discarded when it could still be in use by living components
75 * created from those component classes:
76 *
77 * [component] --ref-> [component class] --through this HT-> [shlib handle]
78 *
79 * This hash table exists for two reasons:
80 *
81 * 1. To allow this application:
82 *
83 * my_plugins = bt_plugin_create_all_from_file("/path/to/my-plugin.so");
84 * // instantiate components from a plugin's component classes
85 * // put plugins and free my_plugins here
86 * // user code of instantiated components still exists
87 *
88 * 2. To decouple the plugin subsystem from the component subsystem:
89 * while plugins objects need to know component class objects, the
90 * opposite is not necessary, thus it makes no sense for a component
91 * class to keep a reference to the plugin object from which it was
92 * created.
93 *
94 * An entry is removed from this HT when a component class is destroyed
95 * thanks to a custom destroy listener. When the entry is removed, the
96 * GLib function calls the value destroy notifier of the HT, which is
97 * bt_put(). This decreases the reference count of the mapped shared
98 * library handle. Assuming the original plugin object which contained
99 * some component classes is put first, when the last component class is
100 * removed from this HT, the shared library handle object's reference
101 * count falls to zero and the shared library is finally closed.
102 */
103static
104GHashTable *comp_classes_to_shlib_handles;
105
106__attribute__((constructor)) static
107void init_comp_classes_to_shlib_handles(void) {
108 comp_classes_to_shlib_handles = g_hash_table_new_full(g_direct_hash,
109 g_direct_equal, NULL, bt_put);
110 assert(comp_classes_to_shlib_handles);
111}
112
113__attribute__((destructor)) static
114void fini_comp_classes_to_shlib_handles(void) {
115 if (comp_classes_to_shlib_handles) {
116 g_hash_table_destroy(comp_classes_to_shlib_handles);
117 }
118}
119
120static
121void bt_plugin_so_shared_lib_handle_destroy(struct bt_object *obj)
122{
123 struct bt_plugin_so_shared_lib_handle *shared_lib_handle;
124
125 assert(obj);
126 shared_lib_handle = container_of(obj,
127 struct bt_plugin_so_shared_lib_handle, base);
128
129 if (shared_lib_handle->init_called && shared_lib_handle->exit) {
130 enum bt_plugin_status status = shared_lib_handle->exit();
131
132 if (status < 0) {
133 const char *path = shared_lib_handle->path ?
134 shared_lib_handle->path->str : "[built-in]";
135
136 printf_verbose("Plugin in module `%s` exited with error %d\n",
137 path, status);
138 }
139 }
140
141 if (shared_lib_handle->module) {
f1447220
PP
142#ifndef NDEBUG
143 /*
144 * Valgrind shows incomplete stack traces when
145 * dynamically loaded libraries are closed before it
146 * finishes. Use the BABELTRACE_NO_DLCLOSE in a debug
147 * build to avoid this.
148 */
149 const char *var = getenv("BABELTRACE_NO_DLCLOSE");
150
151 if (!var || strcmp(var, "1") != 0) {
152#endif
153 if (!g_module_close(shared_lib_handle->module)) {
154 printf_error("Module close error: %s\n",
155 g_module_error());
156 }
157#ifndef NDEBUG
55bb57e0 158 }
f1447220 159#endif
55bb57e0
PP
160 }
161
162 if (shared_lib_handle->path) {
163 g_string_free(shared_lib_handle->path, TRUE);
164 }
165
166 g_free(shared_lib_handle);
167}
168
169static
170struct bt_plugin_so_shared_lib_handle *bt_plugin_so_shared_lib_handle_create(
171 const char *path)
172{
173 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
174
175 shared_lib_handle = g_new0(struct bt_plugin_so_shared_lib_handle, 1);
176 if (!shared_lib_handle) {
177 goto error;
178 }
179
180 bt_object_init(shared_lib_handle, bt_plugin_so_shared_lib_handle_destroy);
181
182 if (!path) {
183 goto end;
184 }
185
186 shared_lib_handle->path = g_string_new(path);
187 if (!shared_lib_handle->path) {
188 goto error;
189 }
190
191 shared_lib_handle->module = g_module_open(path, 0);
192 if (!shared_lib_handle->module) {
193 printf_verbose("Module open error: %s\n", g_module_error());
194 goto error;
195 }
196
197 goto end;
198
199error:
200 BT_PUT(shared_lib_handle);
201
202end:
203 return shared_lib_handle;
204}
205
6fbd4105 206static
55bb57e0
PP
207void bt_plugin_so_destroy_spec_data(struct bt_plugin *plugin)
208{
209 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
210
211 if (!plugin->spec_data) {
212 return;
213 }
214
215 assert(plugin->type == BT_PLUGIN_TYPE_SO);
216 assert(spec);
217 BT_PUT(spec->shared_lib_handle);
218 g_free(plugin->spec_data);
219 plugin->spec_data = NULL;
220}
221
222/*
223 * This function does the following:
224 *
225 * 1. Iterate on the plugin descriptor attributes section and set the
226 * plugin's attributes depending on the attribute types. This
227 * includes the name of the plugin, its description, and its
228 * initialization function, for example.
229 *
230 * 2. Iterate on the component class descriptors section and create one
231 * "full descriptor" (temporary structure) for each one that is found
232 * and attached to our plugin descriptor.
233 *
234 * 3. Iterate on the component class descriptor attributes section and
235 * set the corresponding full descriptor's attributes depending on
236 * the attribute types. This includes the description of the
237 * component class, as well as its initialization and destroy
238 * methods.
239 *
240 * 4. Call the user's plugin initialization function, if any is
241 * defined.
242 *
243 * 5. For each full component class descriptor, create a component class
244 * object, set its optional attributes, and add it to the plugin
245 * object.
246 *
247 * 6. Freeze the plugin object.
248 */
249static
250enum bt_plugin_status bt_plugin_so_init(
251 struct bt_plugin *plugin,
252 const struct __bt_plugin_descriptor *descriptor,
253 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
254 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
255 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
256 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
257 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
258 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
259{
260 /*
261 * This structure's members point to the plugin's memory
262 * (do NOT free).
263 */
264 struct comp_class_full_descriptor {
265 const struct __bt_plugin_component_class_descriptor *descriptor;
266 const char *description;
279b3f15 267 const char *help;
55bb57e0 268 bt_component_class_init_method init_method;
64cadc66 269 bt_component_class_finalize_method finalize_method;
a67681c1 270 bt_component_class_query_method query_method;
72b913fb 271 bt_component_class_accept_port_connection_method accept_port_connection_method;
0d8b4d8e 272 bt_component_class_port_connected_method port_connected_method;
72b913fb 273 bt_component_class_port_disconnected_method port_disconnected_method;
55bb57e0
PP
274 struct bt_component_class_iterator_methods iterator_methods;
275 };
276
277 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
278 struct __bt_plugin_descriptor_attribute const * const *cur_attr_ptr;
279 struct __bt_plugin_component_class_descriptor const * const *cur_cc_descr_ptr;
280 struct __bt_plugin_component_class_descriptor_attribute const * const *cur_cc_descr_attr_ptr;
281 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
282 GArray *comp_class_full_descriptors;
283 size_t i;
284 int ret;
285
286 comp_class_full_descriptors = g_array_new(FALSE, TRUE,
287 sizeof(struct comp_class_full_descriptor));
288 if (!comp_class_full_descriptors) {
289 status = BT_PLUGIN_STATUS_ERROR;
290 goto end;
291 }
292
293 /* Set mandatory attributes */
294 spec->descriptor = descriptor;
295 bt_plugin_set_name(plugin, descriptor->name);
296
297 /*
298 * Find and set optional attributes attached to this plugin
299 * descriptor.
300 */
301 for (cur_attr_ptr = attrs_begin; cur_attr_ptr != attrs_end; cur_attr_ptr++) {
302 const struct __bt_plugin_descriptor_attribute *cur_attr =
303 *cur_attr_ptr;
304
305 if (cur_attr->plugin_descriptor != descriptor) {
306 continue;
307 }
308
309 switch (cur_attr->type) {
310 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT:
311 spec->init = cur_attr->value.init;
312 break;
313 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT:
314 spec->shared_lib_handle->exit = cur_attr->value.exit;
315 break;
316 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR:
317 bt_plugin_set_author(plugin, cur_attr->value.author);
318 break;
319 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE:
320 bt_plugin_set_license(plugin, cur_attr->value.license);
321 break;
322 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
323 bt_plugin_set_description(plugin, cur_attr->value.description);
324 break;
325 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION:
326 bt_plugin_set_version(plugin,
327 (unsigned int) cur_attr->value.version.major,
328 (unsigned int) cur_attr->value.version.minor,
329 (unsigned int) cur_attr->value.version.patch,
330 cur_attr->value.version.extra);
331 break;
332 default:
333 printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for plugin %s\n",
334 cur_attr->type_name, cur_attr->type,
335 descriptor->name);
336 break;
337 }
338 }
339
340 /*
341 * Find component class descriptors attached to this plugin
342 * descriptor and initialize corresponding full component class
343 * descriptors in the array.
344 */
345 for (cur_cc_descr_ptr = cc_descriptors_begin; cur_cc_descr_ptr != cc_descriptors_end; cur_cc_descr_ptr++) {
346 const struct __bt_plugin_component_class_descriptor *cur_cc_descr =
347 *cur_cc_descr_ptr;
348 struct comp_class_full_descriptor full_descriptor = {0};
349
350 if (cur_cc_descr->plugin_descriptor != descriptor) {
351 continue;
352 }
353
354 full_descriptor.descriptor = cur_cc_descr;
355 g_array_append_val(comp_class_full_descriptors,
356 full_descriptor);
357 }
358
359 /*
360 * Find component class descriptor attributes attached to this
361 * plugin descriptor and update corresponding full component
362 * class descriptors in the array.
363 */
364 for (cur_cc_descr_attr_ptr = cc_descr_attrs_begin; cur_cc_descr_attr_ptr != cc_descr_attrs_end; cur_cc_descr_attr_ptr++) {
365 const struct __bt_plugin_component_class_descriptor_attribute *cur_cc_descr_attr =
366 *cur_cc_descr_attr_ptr;
367
368 if (cur_cc_descr_attr->comp_class_descriptor->plugin_descriptor !=
369 descriptor) {
370 continue;
371 }
372
373 /* Find the corresponding component class descriptor entry */
374 for (i = 0; i < comp_class_full_descriptors->len; i++) {
375 struct comp_class_full_descriptor *cc_full_descr =
376 &g_array_index(comp_class_full_descriptors,
377 struct comp_class_full_descriptor, i);
378
379 if (cur_cc_descr_attr->comp_class_descriptor ==
380 cc_full_descr->descriptor) {
381 switch (cur_cc_descr_attr->type) {
382 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
383 cc_full_descr->description =
384 cur_cc_descr_attr->value.description;
385 break;
279b3f15
PP
386 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP:
387 cc_full_descr->help =
388 cur_cc_descr_attr->value.help;
389 break;
55bb57e0
PP
390 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INIT_METHOD:
391 cc_full_descr->init_method =
392 cur_cc_descr_attr->value.init_method;
393 break;
64cadc66
PP
394 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD:
395 cc_full_descr->finalize_method =
396 cur_cc_descr_attr->value.finalize_method;
55bb57e0 397 break;
a67681c1
PP
398 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD:
399 cc_full_descr->query_method =
400 cur_cc_descr_attr->value.query_method;
8463eac2 401 break;
72b913fb
PP
402 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_ACCEPT_PORT_CONNECTION_METHOD:
403 cc_full_descr->accept_port_connection_method =
404 cur_cc_descr_attr->value.accept_port_connection_method;
405 break;
0d8b4d8e
PP
406 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD:
407 cc_full_descr->port_connected_method =
408 cur_cc_descr_attr->value.port_connected_method;
409 break;
72b913fb
PP
410 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_DISCONNECTED_METHOD:
411 cc_full_descr->port_disconnected_method =
412 cur_cc_descr_attr->value.port_disconnected_method;
55bb57e0
PP
413 break;
414 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_INIT_METHOD:
415 cc_full_descr->iterator_methods.init =
416 cur_cc_descr_attr->value.notif_iter_init_method;
417 break;
64cadc66
PP
418 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_FINALIZE_METHOD:
419 cc_full_descr->iterator_methods.finalize =
420 cur_cc_descr_attr->value.notif_iter_finalize_method;
55bb57e0
PP
421 break;
422 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_SEEK_TIME_METHOD:
423 cc_full_descr->iterator_methods.seek_time =
424 cur_cc_descr_attr->value.notif_iter_seek_time_method;
425 break;
426 default:
427 printf_verbose("WARNING: Unknown attribute \"%s\" (type %d) for component class %s (type %d) in plugin %s\n",
428 cur_cc_descr_attr->type_name,
429 cur_cc_descr_attr->type,
430 cur_cc_descr_attr->comp_class_descriptor->name,
431 cur_cc_descr_attr->comp_class_descriptor->type,
432 descriptor->name);
433 break;
434 }
435 }
436 }
437 }
438
439 /* Initialize plugin */
440 if (spec->init) {
441 status = spec->init(plugin);
442 if (status < 0) {
443 printf_verbose("Plugin `%s` initialization error: %d\n",
444 bt_plugin_get_name(plugin), status);
445 goto end;
446 }
447 }
448
c55a9f58 449 spec->shared_lib_handle->init_called = BT_TRUE;
55bb57e0
PP
450
451 /* Add described component classes to plugin */
452 for (i = 0; i < comp_class_full_descriptors->len; i++) {
453 struct comp_class_full_descriptor *cc_full_descr =
454 &g_array_index(comp_class_full_descriptors,
455 struct comp_class_full_descriptor, i);
456 struct bt_component_class *comp_class;
457
458 switch (cc_full_descr->descriptor->type) {
459 case BT_COMPONENT_CLASS_TYPE_SOURCE:
460 comp_class = bt_component_class_source_create(
461 cc_full_descr->descriptor->name,
55bb57e0
PP
462 cc_full_descr->descriptor->methods.source.notif_iter_next);
463 break;
464 case BT_COMPONENT_CLASS_TYPE_FILTER:
465 comp_class = bt_component_class_filter_create(
466 cc_full_descr->descriptor->name,
55bb57e0
PP
467 cc_full_descr->descriptor->methods.source.notif_iter_next);
468 break;
469 case BT_COMPONENT_CLASS_TYPE_SINK:
470 comp_class = bt_component_class_sink_create(
471 cc_full_descr->descriptor->name,
472 cc_full_descr->descriptor->methods.sink.consume);
473 break;
474 default:
475 printf_verbose("WARNING: Unknown component class type %d for component class %s in plugin %s\n",
476 cc_full_descr->descriptor->type,
477 cc_full_descr->descriptor->name,
478 descriptor->name);
479 continue;
480 }
481
482 if (!comp_class) {
483 status = BT_PLUGIN_STATUS_ERROR;
484 goto end;
485 }
486
487 if (cc_full_descr->description) {
488 ret = bt_component_class_set_description(comp_class,
489 cc_full_descr->description);
490 if (ret) {
491 status = BT_PLUGIN_STATUS_ERROR;
492 BT_PUT(comp_class);
493 goto end;
494 }
495 }
496
279b3f15
PP
497 if (cc_full_descr->help) {
498 ret = bt_component_class_set_help(comp_class,
499 cc_full_descr->help);
500 if (ret) {
501 status = BT_PLUGIN_STATUS_ERROR;
502 BT_PUT(comp_class);
503 goto end;
504 }
505 }
506
55bb57e0
PP
507 if (cc_full_descr->init_method) {
508 ret = bt_component_class_set_init_method(comp_class,
509 cc_full_descr->init_method);
510 if (ret) {
511 status = BT_PLUGIN_STATUS_ERROR;
512 BT_PUT(comp_class);
513 goto end;
514 }
515 }
516
64cadc66
PP
517 if (cc_full_descr->finalize_method) {
518 ret = bt_component_class_set_finalize_method(comp_class,
519 cc_full_descr->finalize_method);
55bb57e0
PP
520 if (ret) {
521 status = BT_PLUGIN_STATUS_ERROR;
522 BT_PUT(comp_class);
523 goto end;
524 }
525 }
526
a67681c1
PP
527 if (cc_full_descr->query_method) {
528 ret = bt_component_class_set_query_method(
529 comp_class, cc_full_descr->query_method);
8463eac2
PP
530 if (ret) {
531 status = BT_PLUGIN_STATUS_ERROR;
532 BT_PUT(comp_class);
533 goto end;
534 }
535 }
536
72b913fb
PP
537 if (cc_full_descr->accept_port_connection_method) {
538 ret = bt_component_class_set_accept_port_connection_method(
539 comp_class, cc_full_descr->accept_port_connection_method);
540 if (ret) {
541 status = BT_PLUGIN_STATUS_ERROR;
542 BT_PUT(comp_class);
543 goto end;
544 }
545 }
546
0d8b4d8e
PP
547 if (cc_full_descr->port_connected_method) {
548 ret = bt_component_class_set_port_connected_method(
549 comp_class, cc_full_descr->port_connected_method);
550 if (ret) {
551 status = BT_PLUGIN_STATUS_ERROR;
552 BT_PUT(comp_class);
553 goto end;
554 }
555 }
556
72b913fb
PP
557 if (cc_full_descr->port_disconnected_method) {
558 ret = bt_component_class_set_port_disconnected_method(
559 comp_class, cc_full_descr->port_disconnected_method);
2d41b99e
JG
560 if (ret) {
561 status = BT_PLUGIN_STATUS_ERROR;
562 BT_PUT(comp_class);
563 goto end;
564 }
565 }
566
55bb57e0
PP
567 switch (cc_full_descr->descriptor->type) {
568 case BT_COMPONENT_CLASS_TYPE_SOURCE:
569 if (cc_full_descr->iterator_methods.init) {
570 ret = bt_component_class_source_set_notification_iterator_init_method(
571 comp_class,
572 cc_full_descr->iterator_methods.init);
573 if (ret) {
574 status = BT_PLUGIN_STATUS_ERROR;
575 BT_PUT(comp_class);
576 goto end;
577 }
578 }
579
64cadc66
PP
580 if (cc_full_descr->iterator_methods.finalize) {
581 ret = bt_component_class_source_set_notification_iterator_finalize_method(
55bb57e0 582 comp_class,
64cadc66 583 cc_full_descr->iterator_methods.finalize);
55bb57e0
PP
584 if (ret) {
585 status = BT_PLUGIN_STATUS_ERROR;
586 BT_PUT(comp_class);
587 goto end;
588 }
589 }
590
591 if (cc_full_descr->iterator_methods.seek_time) {
592 ret = bt_component_class_source_set_notification_iterator_seek_time_method(
593 comp_class,
594 cc_full_descr->iterator_methods.seek_time);
595 if (ret) {
596 status = BT_PLUGIN_STATUS_ERROR;
597 BT_PUT(comp_class);
598 goto end;
599 }
600 }
601 break;
602 case BT_COMPONENT_CLASS_TYPE_FILTER:
55bb57e0
PP
603 if (cc_full_descr->iterator_methods.init) {
604 ret = bt_component_class_filter_set_notification_iterator_init_method(
605 comp_class,
606 cc_full_descr->iterator_methods.init);
607 if (ret) {
608 status = BT_PLUGIN_STATUS_ERROR;
609 BT_PUT(comp_class);
610 goto end;
611 }
612 }
613
64cadc66
PP
614 if (cc_full_descr->iterator_methods.finalize) {
615 ret = bt_component_class_filter_set_notification_iterator_finalize_method(
55bb57e0 616 comp_class,
64cadc66 617 cc_full_descr->iterator_methods.finalize);
55bb57e0
PP
618 if (ret) {
619 status = BT_PLUGIN_STATUS_ERROR;
620 BT_PUT(comp_class);
621 goto end;
622 }
623 }
624
625 if (cc_full_descr->iterator_methods.seek_time) {
626 ret = bt_component_class_filter_set_notification_iterator_seek_time_method(
627 comp_class,
628 cc_full_descr->iterator_methods.seek_time);
629 if (ret) {
630 status = BT_PLUGIN_STATUS_ERROR;
631 BT_PUT(comp_class);
632 goto end;
633 }
634 }
635 break;
636 case BT_COMPONENT_CLASS_TYPE_SINK:
55bb57e0
PP
637 break;
638 default:
0fbb9a9f 639 abort();
55bb57e0
PP
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.064619 seconds and 4 git commands to generate.