Fix: make Python plugin provider have its own log level
[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
3fe0bf43
PP
30#define BT_LOG_TAG "PLUGIN-SO"
31#include <babeltrace/lib-logging-internal.h>
32
3d9990ac 33#include <babeltrace/compiler-internal.h>
55bb57e0
PP
34#include <babeltrace/ref.h>
35#include <babeltrace/plugin/plugin-internal.h>
36#include <babeltrace/plugin/plugin-so-internal.h>
37#include <babeltrace/plugin/plugin-dev.h>
38#include <babeltrace/plugin/plugin-internal.h>
b2e0c907 39#include <babeltrace/graph/component-class-internal.h>
c55a9f58 40#include <babeltrace/types.h>
55bb57e0 41#include <string.h>
0fbb9a9f 42#include <stdlib.h>
55bb57e0
PP
43#include <glib.h>
44#include <gmodule.h>
45
46#define NATIVE_PLUGIN_SUFFIX ".so"
47#define NATIVE_PLUGIN_SUFFIX_LEN sizeof(NATIVE_PLUGIN_SUFFIX)
48#define LIBTOOL_PLUGIN_SUFFIX ".la"
49#define LIBTOOL_PLUGIN_SUFFIX_LEN sizeof(LIBTOOL_PLUGIN_SUFFIX)
50
51#define PLUGIN_SUFFIX_LEN max_t(size_t, sizeof(NATIVE_PLUGIN_SUFFIX), \
52 sizeof(LIBTOOL_PLUGIN_SUFFIX))
53
54#define SECTION_BEGIN(_name) (&(__start_##_name))
55#define SECTION_END(_name) (&(__stop_##_name))
56#define SECTION_ELEMENT_COUNT(_name) (SECTION_END(_name) - SECTION_BEGIN(_name))
57
58#define DECLARE_SECTION(_type, _name) \
59 extern _type __start_##_name __attribute((weak)); \
60 extern _type __stop_##_name __attribute((weak))
61
62DECLARE_SECTION(struct __bt_plugin_descriptor const *, __bt_plugin_descriptors);
63DECLARE_SECTION(struct __bt_plugin_descriptor_attribute const *, __bt_plugin_descriptor_attributes);
64DECLARE_SECTION(struct __bt_plugin_component_class_descriptor const *, __bt_plugin_component_class_descriptors);
65DECLARE_SECTION(struct __bt_plugin_component_class_descriptor_attribute const *, __bt_plugin_component_class_descriptor_attributes);
66
67/*
68 * This hash table, global to the library, maps component class pointers
69 * to shared library handles.
70 *
71 * The keys (component classes) are NOT owned by this hash table, whereas
72 * the values (shared library handles) are owned by this hash table.
73 *
74 * The keys are the component classes created with
75 * bt_plugin_add_component_class(). They keep the shared library handle
76 * object created by their plugin alive so that the plugin's code is
77 * not discarded when it could still be in use by living components
78 * created from those component classes:
79 *
80 * [component] --ref-> [component class] --through this HT-> [shlib handle]
81 *
82 * This hash table exists for two reasons:
83 *
84 * 1. To allow this application:
85 *
86 * my_plugins = bt_plugin_create_all_from_file("/path/to/my-plugin.so");
87 * // instantiate components from a plugin's component classes
88 * // put plugins and free my_plugins here
89 * // user code of instantiated components still exists
90 *
91 * 2. To decouple the plugin subsystem from the component subsystem:
92 * while plugins objects need to know component class objects, the
93 * opposite is not necessary, thus it makes no sense for a component
94 * class to keep a reference to the plugin object from which it was
95 * created.
96 *
97 * An entry is removed from this HT when a component class is destroyed
98 * thanks to a custom destroy listener. When the entry is removed, the
99 * GLib function calls the value destroy notifier of the HT, which is
100 * bt_put(). This decreases the reference count of the mapped shared
101 * library handle. Assuming the original plugin object which contained
102 * some component classes is put first, when the last component class is
103 * removed from this HT, the shared library handle object's reference
104 * count falls to zero and the shared library is finally closed.
105 */
106static
107GHashTable *comp_classes_to_shlib_handles;
108
109__attribute__((constructor)) static
110void init_comp_classes_to_shlib_handles(void) {
111 comp_classes_to_shlib_handles = g_hash_table_new_full(g_direct_hash,
112 g_direct_equal, NULL, bt_put);
113 assert(comp_classes_to_shlib_handles);
3fe0bf43 114 BT_LOGD_STR("Initialized component class to shared library handle hash table.");
55bb57e0
PP
115}
116
117__attribute__((destructor)) static
118void fini_comp_classes_to_shlib_handles(void) {
119 if (comp_classes_to_shlib_handles) {
120 g_hash_table_destroy(comp_classes_to_shlib_handles);
3fe0bf43 121 BT_LOGD_STR("Destroyed component class to shared library handle hash table.");
55bb57e0
PP
122 }
123}
124
125static
126void bt_plugin_so_shared_lib_handle_destroy(struct bt_object *obj)
127{
128 struct bt_plugin_so_shared_lib_handle *shared_lib_handle;
129
130 assert(obj);
131 shared_lib_handle = container_of(obj,
132 struct bt_plugin_so_shared_lib_handle, base);
3fe0bf43
PP
133 const char *path = shared_lib_handle->path ?
134 shared_lib_handle->path->str : NULL;
135
136 BT_LOGD("Destroying shared library handle: addr=%p, path=\"%s\"",
137 shared_lib_handle, path);
55bb57e0
PP
138
139 if (shared_lib_handle->init_called && shared_lib_handle->exit) {
3fe0bf43 140 enum bt_plugin_status status;
55bb57e0 141
3fe0bf43
PP
142 BT_LOGD_STR("Calling user's plugin exit function.");
143 status = shared_lib_handle->exit();
144 BT_LOGD("User function returned: %s",
145 bt_plugin_status_string(status));
55bb57e0 146
3fe0bf43
PP
147 if (status < 0) {
148 BT_LOGW("User's plugin exit function failed: "
149 "path=\"%s\"", path);
55bb57e0
PP
150 }
151 }
152
153 if (shared_lib_handle->module) {
f1447220
PP
154#ifndef NDEBUG
155 /*
156 * Valgrind shows incomplete stack traces when
157 * dynamically loaded libraries are closed before it
158 * finishes. Use the BABELTRACE_NO_DLCLOSE in a debug
159 * build to avoid this.
160 */
161 const char *var = getenv("BABELTRACE_NO_DLCLOSE");
162
163 if (!var || strcmp(var, "1") != 0) {
164#endif
3fe0bf43
PP
165 BT_LOGD("Closing GModule: path=\"%s\"", path);
166
f1447220 167 if (!g_module_close(shared_lib_handle->module)) {
3fe0bf43
PP
168 BT_LOGE("Cannot close GModule: %s: path=\"%s\"",
169 g_module_error(), path);
f1447220
PP
170 }
171#ifndef NDEBUG
3fe0bf43
PP
172 } else {
173 BT_LOGD("Not closing GModule because `BABELTRACE_NO_DLCLOSE=1`: "
174 "path=\"%s\"", path);
55bb57e0 175 }
f1447220 176#endif
55bb57e0
PP
177 }
178
179 if (shared_lib_handle->path) {
180 g_string_free(shared_lib_handle->path, TRUE);
181 }
182
183 g_free(shared_lib_handle);
184}
185
186static
187struct bt_plugin_so_shared_lib_handle *bt_plugin_so_shared_lib_handle_create(
188 const char *path)
189{
190 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
191
3fe0bf43 192 BT_LOGD("Creating shared library handle: path=\"%s\"", path);
55bb57e0
PP
193 shared_lib_handle = g_new0(struct bt_plugin_so_shared_lib_handle, 1);
194 if (!shared_lib_handle) {
3fe0bf43 195 BT_LOGE_STR("Failed to allocate one shared library handle.");
55bb57e0
PP
196 goto error;
197 }
198
199 bt_object_init(shared_lib_handle, bt_plugin_so_shared_lib_handle_destroy);
200
201 if (!path) {
202 goto end;
203 }
204
205 shared_lib_handle->path = g_string_new(path);
206 if (!shared_lib_handle->path) {
3fe0bf43 207 BT_LOGE_STR("Failed to allocate a GString.");
55bb57e0
PP
208 goto error;
209 }
210
211 shared_lib_handle->module = g_module_open(path, 0);
212 if (!shared_lib_handle->module) {
3fe0bf43
PP
213 BT_LOGW("Cannot open GModule: %s: path=\"%s\"",
214 g_module_error(), path);
55bb57e0
PP
215 goto error;
216 }
217
218 goto end;
219
220error:
221 BT_PUT(shared_lib_handle);
222
223end:
3fe0bf43
PP
224 if (shared_lib_handle) {
225 BT_LOGD("Created shared library handle: path=\"%s\", addr=%p",
226 path, shared_lib_handle);
227 }
228
55bb57e0
PP
229 return shared_lib_handle;
230}
231
6fbd4105 232static
55bb57e0
PP
233void bt_plugin_so_destroy_spec_data(struct bt_plugin *plugin)
234{
235 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
236
237 if (!plugin->spec_data) {
238 return;
239 }
240
241 assert(plugin->type == BT_PLUGIN_TYPE_SO);
242 assert(spec);
243 BT_PUT(spec->shared_lib_handle);
244 g_free(plugin->spec_data);
245 plugin->spec_data = NULL;
246}
247
248/*
249 * This function does the following:
250 *
251 * 1. Iterate on the plugin descriptor attributes section and set the
252 * plugin's attributes depending on the attribute types. This
253 * includes the name of the plugin, its description, and its
254 * initialization function, for example.
255 *
256 * 2. Iterate on the component class descriptors section and create one
257 * "full descriptor" (temporary structure) for each one that is found
258 * and attached to our plugin descriptor.
259 *
260 * 3. Iterate on the component class descriptor attributes section and
261 * set the corresponding full descriptor's attributes depending on
262 * the attribute types. This includes the description of the
263 * component class, as well as its initialization and destroy
264 * methods.
265 *
266 * 4. Call the user's plugin initialization function, if any is
267 * defined.
268 *
269 * 5. For each full component class descriptor, create a component class
270 * object, set its optional attributes, and add it to the plugin
271 * object.
272 *
273 * 6. Freeze the plugin object.
274 */
275static
276enum bt_plugin_status bt_plugin_so_init(
277 struct bt_plugin *plugin,
278 const struct __bt_plugin_descriptor *descriptor,
279 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
280 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
281 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
282 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
283 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
284 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
285{
286 /*
287 * This structure's members point to the plugin's memory
288 * (do NOT free).
289 */
290 struct comp_class_full_descriptor {
291 const struct __bt_plugin_component_class_descriptor *descriptor;
292 const char *description;
279b3f15 293 const char *help;
55bb57e0 294 bt_component_class_init_method init_method;
64cadc66 295 bt_component_class_finalize_method finalize_method;
a67681c1 296 bt_component_class_query_method query_method;
72b913fb 297 bt_component_class_accept_port_connection_method accept_port_connection_method;
0d8b4d8e 298 bt_component_class_port_connected_method port_connected_method;
72b913fb 299 bt_component_class_port_disconnected_method port_disconnected_method;
55bb57e0
PP
300 struct bt_component_class_iterator_methods iterator_methods;
301 };
302
303 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
304 struct __bt_plugin_descriptor_attribute const * const *cur_attr_ptr;
305 struct __bt_plugin_component_class_descriptor const * const *cur_cc_descr_ptr;
306 struct __bt_plugin_component_class_descriptor_attribute const * const *cur_cc_descr_attr_ptr;
307 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
308 GArray *comp_class_full_descriptors;
309 size_t i;
310 int ret;
311
3fe0bf43
PP
312 BT_LOGD("Initializing plugin object from descriptors found in sections: "
313 "plugin-addr=%p, plugin-path=\"%s\", "
314 "attrs-begin-addr=%p, attrs-end-addr=%p, "
315 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
316 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p",
317 plugin,
318 spec->shared_lib_handle->path ?
319 spec->shared_lib_handle->path->str : NULL,
320 attrs_begin, attrs_end,
321 cc_descriptors_begin, cc_descriptors_end,
322 cc_descr_attrs_begin, cc_descr_attrs_end);
55bb57e0
PP
323 comp_class_full_descriptors = g_array_new(FALSE, TRUE,
324 sizeof(struct comp_class_full_descriptor));
325 if (!comp_class_full_descriptors) {
3fe0bf43 326 BT_LOGE_STR("Failed to allocate a GArray.");
55bb57e0
PP
327 status = BT_PLUGIN_STATUS_ERROR;
328 goto end;
329 }
330
331 /* Set mandatory attributes */
332 spec->descriptor = descriptor;
333 bt_plugin_set_name(plugin, descriptor->name);
334
335 /*
336 * Find and set optional attributes attached to this plugin
337 * descriptor.
338 */
339 for (cur_attr_ptr = attrs_begin; cur_attr_ptr != attrs_end; cur_attr_ptr++) {
340 const struct __bt_plugin_descriptor_attribute *cur_attr =
341 *cur_attr_ptr;
342
343 if (cur_attr->plugin_descriptor != descriptor) {
344 continue;
345 }
346
347 switch (cur_attr->type) {
348 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT:
349 spec->init = cur_attr->value.init;
350 break;
351 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT:
352 spec->shared_lib_handle->exit = cur_attr->value.exit;
353 break;
354 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR:
355 bt_plugin_set_author(plugin, cur_attr->value.author);
356 break;
357 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE:
358 bt_plugin_set_license(plugin, cur_attr->value.license);
359 break;
360 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
361 bt_plugin_set_description(plugin, cur_attr->value.description);
362 break;
363 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION:
364 bt_plugin_set_version(plugin,
365 (unsigned int) cur_attr->value.version.major,
366 (unsigned int) cur_attr->value.version.minor,
367 (unsigned int) cur_attr->value.version.patch,
368 cur_attr->value.version.extra);
369 break;
370 default:
3fe0bf43
PP
371 BT_LOGW("Ignoring unknown plugin descriptor attribute: "
372 "plugin-path=\"%s\", plugin-name=\"%s\", "
373 "attr-type-name=\"%s\", attr-type-id=%d",
374 spec->shared_lib_handle->path ?
375 spec->shared_lib_handle->path->str :
376 NULL,
377 descriptor->name, cur_attr->type_name,
378 cur_attr->type);
55bb57e0
PP
379 break;
380 }
381 }
382
383 /*
384 * Find component class descriptors attached to this plugin
385 * descriptor and initialize corresponding full component class
386 * descriptors in the array.
387 */
388 for (cur_cc_descr_ptr = cc_descriptors_begin; cur_cc_descr_ptr != cc_descriptors_end; cur_cc_descr_ptr++) {
389 const struct __bt_plugin_component_class_descriptor *cur_cc_descr =
390 *cur_cc_descr_ptr;
391 struct comp_class_full_descriptor full_descriptor = {0};
392
393 if (cur_cc_descr->plugin_descriptor != descriptor) {
394 continue;
395 }
396
397 full_descriptor.descriptor = cur_cc_descr;
398 g_array_append_val(comp_class_full_descriptors,
399 full_descriptor);
400 }
401
402 /*
403 * Find component class descriptor attributes attached to this
404 * plugin descriptor and update corresponding full component
405 * class descriptors in the array.
406 */
407 for (cur_cc_descr_attr_ptr = cc_descr_attrs_begin; cur_cc_descr_attr_ptr != cc_descr_attrs_end; cur_cc_descr_attr_ptr++) {
408 const struct __bt_plugin_component_class_descriptor_attribute *cur_cc_descr_attr =
409 *cur_cc_descr_attr_ptr;
410
411 if (cur_cc_descr_attr->comp_class_descriptor->plugin_descriptor !=
412 descriptor) {
413 continue;
414 }
415
416 /* Find the corresponding component class descriptor entry */
417 for (i = 0; i < comp_class_full_descriptors->len; i++) {
418 struct comp_class_full_descriptor *cc_full_descr =
419 &g_array_index(comp_class_full_descriptors,
420 struct comp_class_full_descriptor, i);
421
422 if (cur_cc_descr_attr->comp_class_descriptor ==
423 cc_full_descr->descriptor) {
424 switch (cur_cc_descr_attr->type) {
425 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
426 cc_full_descr->description =
427 cur_cc_descr_attr->value.description;
428 break;
279b3f15
PP
429 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP:
430 cc_full_descr->help =
431 cur_cc_descr_attr->value.help;
432 break;
55bb57e0
PP
433 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INIT_METHOD:
434 cc_full_descr->init_method =
435 cur_cc_descr_attr->value.init_method;
436 break;
64cadc66
PP
437 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD:
438 cc_full_descr->finalize_method =
439 cur_cc_descr_attr->value.finalize_method;
55bb57e0 440 break;
a67681c1
PP
441 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD:
442 cc_full_descr->query_method =
443 cur_cc_descr_attr->value.query_method;
8463eac2 444 break;
72b913fb
PP
445 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_ACCEPT_PORT_CONNECTION_METHOD:
446 cc_full_descr->accept_port_connection_method =
447 cur_cc_descr_attr->value.accept_port_connection_method;
448 break;
0d8b4d8e
PP
449 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD:
450 cc_full_descr->port_connected_method =
451 cur_cc_descr_attr->value.port_connected_method;
452 break;
72b913fb
PP
453 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_DISCONNECTED_METHOD:
454 cc_full_descr->port_disconnected_method =
455 cur_cc_descr_attr->value.port_disconnected_method;
55bb57e0
PP
456 break;
457 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_INIT_METHOD:
458 cc_full_descr->iterator_methods.init =
459 cur_cc_descr_attr->value.notif_iter_init_method;
460 break;
64cadc66
PP
461 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_FINALIZE_METHOD:
462 cc_full_descr->iterator_methods.finalize =
463 cur_cc_descr_attr->value.notif_iter_finalize_method;
55bb57e0
PP
464 break;
465 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_SEEK_TIME_METHOD:
466 cc_full_descr->iterator_methods.seek_time =
467 cur_cc_descr_attr->value.notif_iter_seek_time_method;
468 break;
469 default:
3fe0bf43
PP
470 BT_LOGW("Ignoring unknown component class descriptor attribute: "
471 "plugin-path=\"%s\", "
472 "plugin-name=\"%s\", "
473 "comp-class-name=\"%s\", "
474 "comp-class-type=%s, "
475 "attr-type-name=\"%s\", "
476 "attr-type-id=%d",
477 spec->shared_lib_handle->path ?
478 spec->shared_lib_handle->path->str :
479 NULL,
480 descriptor->name,
55bb57e0 481 cur_cc_descr_attr->comp_class_descriptor->name,
3fe0bf43
PP
482 bt_component_class_type_string(
483 cur_cc_descr_attr->comp_class_descriptor->type),
484 cur_cc_descr_attr->type_name,
485 cur_cc_descr_attr->type);
55bb57e0
PP
486 break;
487 }
488 }
489 }
490 }
491
492 /* Initialize plugin */
493 if (spec->init) {
3fe0bf43 494 BT_LOGD_STR("Calling user's plugin initialization function.");
55bb57e0 495 status = spec->init(plugin);
3fe0bf43
PP
496 BT_LOGD("User function returned: %s",
497 bt_plugin_status_string(status));
498
55bb57e0 499 if (status < 0) {
3fe0bf43 500 BT_LOGW_STR("User's plugin initialization function failed.");
55bb57e0
PP
501 goto end;
502 }
503 }
504
c55a9f58 505 spec->shared_lib_handle->init_called = BT_TRUE;
55bb57e0
PP
506
507 /* Add described component classes to plugin */
508 for (i = 0; i < comp_class_full_descriptors->len; i++) {
509 struct comp_class_full_descriptor *cc_full_descr =
510 &g_array_index(comp_class_full_descriptors,
511 struct comp_class_full_descriptor, i);
512 struct bt_component_class *comp_class;
513
3fe0bf43
PP
514 BT_LOGD("Creating and setting properties of plugin's component class: "
515 "plugin-path=\"%s\", plugin-name=\"%s\", "
516 "comp-class-name=\"%s\", comp-class-type=%s",
517 spec->shared_lib_handle->path ?
518 spec->shared_lib_handle->path->str :
519 NULL,
520 descriptor->name,
521 cc_full_descr->descriptor->name,
522 bt_component_class_type_string(
523 cc_full_descr->descriptor->type));
524
55bb57e0
PP
525 switch (cc_full_descr->descriptor->type) {
526 case BT_COMPONENT_CLASS_TYPE_SOURCE:
527 comp_class = bt_component_class_source_create(
528 cc_full_descr->descriptor->name,
55bb57e0
PP
529 cc_full_descr->descriptor->methods.source.notif_iter_next);
530 break;
531 case BT_COMPONENT_CLASS_TYPE_FILTER:
532 comp_class = bt_component_class_filter_create(
533 cc_full_descr->descriptor->name,
55bb57e0
PP
534 cc_full_descr->descriptor->methods.source.notif_iter_next);
535 break;
536 case BT_COMPONENT_CLASS_TYPE_SINK:
537 comp_class = bt_component_class_sink_create(
538 cc_full_descr->descriptor->name,
539 cc_full_descr->descriptor->methods.sink.consume);
540 break;
541 default:
3fe0bf43
PP
542 BT_LOGW("Ignoring unknown component class type: "
543 "plugin-path=\"%s\", plugin-name=\"%s\", "
544 "comp-class-name=\"%s\", comp-class-type=%d",
545 spec->shared_lib_handle->path->str ?
546 spec->shared_lib_handle->path->str :
547 NULL,
548 descriptor->name,
55bb57e0 549 cc_full_descr->descriptor->name,
3fe0bf43 550 cc_full_descr->descriptor->type);
55bb57e0
PP
551 continue;
552 }
553
554 if (!comp_class) {
3fe0bf43 555 BT_LOGE_STR("Cannot create component class.");
55bb57e0
PP
556 status = BT_PLUGIN_STATUS_ERROR;
557 goto end;
558 }
559
560 if (cc_full_descr->description) {
561 ret = bt_component_class_set_description(comp_class,
562 cc_full_descr->description);
563 if (ret) {
3fe0bf43 564 BT_LOGE_STR("Cannot set component class's description.");
55bb57e0
PP
565 status = BT_PLUGIN_STATUS_ERROR;
566 BT_PUT(comp_class);
567 goto end;
568 }
569 }
570
279b3f15
PP
571 if (cc_full_descr->help) {
572 ret = bt_component_class_set_help(comp_class,
573 cc_full_descr->help);
574 if (ret) {
3fe0bf43 575 BT_LOGE_STR("Cannot set component class's help string.");
279b3f15
PP
576 status = BT_PLUGIN_STATUS_ERROR;
577 BT_PUT(comp_class);
578 goto end;
579 }
580 }
581
55bb57e0
PP
582 if (cc_full_descr->init_method) {
583 ret = bt_component_class_set_init_method(comp_class,
584 cc_full_descr->init_method);
585 if (ret) {
3fe0bf43 586 BT_LOGE_STR("Cannot set component class's initialization method.");
55bb57e0
PP
587 status = BT_PLUGIN_STATUS_ERROR;
588 BT_PUT(comp_class);
589 goto end;
590 }
591 }
592
64cadc66
PP
593 if (cc_full_descr->finalize_method) {
594 ret = bt_component_class_set_finalize_method(comp_class,
595 cc_full_descr->finalize_method);
55bb57e0 596 if (ret) {
3fe0bf43 597 BT_LOGE_STR("Cannot set component class's finalization method.");
55bb57e0
PP
598 status = BT_PLUGIN_STATUS_ERROR;
599 BT_PUT(comp_class);
600 goto end;
601 }
602 }
603
a67681c1
PP
604 if (cc_full_descr->query_method) {
605 ret = bt_component_class_set_query_method(
606 comp_class, cc_full_descr->query_method);
8463eac2 607 if (ret) {
3fe0bf43 608 BT_LOGE_STR("Cannot set component class's query method.");
8463eac2
PP
609 status = BT_PLUGIN_STATUS_ERROR;
610 BT_PUT(comp_class);
611 goto end;
612 }
613 }
614
72b913fb
PP
615 if (cc_full_descr->accept_port_connection_method) {
616 ret = bt_component_class_set_accept_port_connection_method(
617 comp_class, cc_full_descr->accept_port_connection_method);
618 if (ret) {
3fe0bf43 619 BT_LOGE_STR("Cannot set component class's \"accept port connection\" method.");
72b913fb
PP
620 status = BT_PLUGIN_STATUS_ERROR;
621 BT_PUT(comp_class);
622 goto end;
623 }
624 }
625
0d8b4d8e
PP
626 if (cc_full_descr->port_connected_method) {
627 ret = bt_component_class_set_port_connected_method(
628 comp_class, cc_full_descr->port_connected_method);
629 if (ret) {
3fe0bf43 630 BT_LOGE_STR("Cannot set component class's \"port connected\" method.");
0d8b4d8e
PP
631 status = BT_PLUGIN_STATUS_ERROR;
632 BT_PUT(comp_class);
633 goto end;
634 }
635 }
636
72b913fb
PP
637 if (cc_full_descr->port_disconnected_method) {
638 ret = bt_component_class_set_port_disconnected_method(
639 comp_class, cc_full_descr->port_disconnected_method);
2d41b99e 640 if (ret) {
3fe0bf43 641 BT_LOGE_STR("Cannot set component class's \"port disconnected\" method.");
2d41b99e
JG
642 status = BT_PLUGIN_STATUS_ERROR;
643 BT_PUT(comp_class);
644 goto end;
645 }
646 }
647
55bb57e0
PP
648 switch (cc_full_descr->descriptor->type) {
649 case BT_COMPONENT_CLASS_TYPE_SOURCE:
650 if (cc_full_descr->iterator_methods.init) {
651 ret = bt_component_class_source_set_notification_iterator_init_method(
652 comp_class,
653 cc_full_descr->iterator_methods.init);
654 if (ret) {
3fe0bf43 655 BT_LOGE_STR("Cannot set component class's notification iterator initialization method.");
55bb57e0
PP
656 status = BT_PLUGIN_STATUS_ERROR;
657 BT_PUT(comp_class);
658 goto end;
659 }
660 }
661
64cadc66
PP
662 if (cc_full_descr->iterator_methods.finalize) {
663 ret = bt_component_class_source_set_notification_iterator_finalize_method(
55bb57e0 664 comp_class,
64cadc66 665 cc_full_descr->iterator_methods.finalize);
55bb57e0 666 if (ret) {
3fe0bf43 667 BT_LOGE_STR("Cannot set source component class's notification iterator finalization method.");
55bb57e0
PP
668 status = BT_PLUGIN_STATUS_ERROR;
669 BT_PUT(comp_class);
670 goto end;
671 }
672 }
673
674 if (cc_full_descr->iterator_methods.seek_time) {
675 ret = bt_component_class_source_set_notification_iterator_seek_time_method(
676 comp_class,
677 cc_full_descr->iterator_methods.seek_time);
678 if (ret) {
3fe0bf43 679 BT_LOGE_STR("Cannot set source component class's notification iterator seek to time method.");
55bb57e0
PP
680 status = BT_PLUGIN_STATUS_ERROR;
681 BT_PUT(comp_class);
682 goto end;
683 }
684 }
685 break;
686 case BT_COMPONENT_CLASS_TYPE_FILTER:
55bb57e0
PP
687 if (cc_full_descr->iterator_methods.init) {
688 ret = bt_component_class_filter_set_notification_iterator_init_method(
689 comp_class,
690 cc_full_descr->iterator_methods.init);
691 if (ret) {
3fe0bf43 692 BT_LOGE_STR("Cannot set filter component class's notification iterator initialization method.");
55bb57e0
PP
693 status = BT_PLUGIN_STATUS_ERROR;
694 BT_PUT(comp_class);
695 goto end;
696 }
697 }
698
64cadc66
PP
699 if (cc_full_descr->iterator_methods.finalize) {
700 ret = bt_component_class_filter_set_notification_iterator_finalize_method(
55bb57e0 701 comp_class,
64cadc66 702 cc_full_descr->iterator_methods.finalize);
55bb57e0 703 if (ret) {
3fe0bf43 704 BT_LOGE_STR("Cannot set filter component class's notification iterator finalization method.");
55bb57e0
PP
705 status = BT_PLUGIN_STATUS_ERROR;
706 BT_PUT(comp_class);
707 goto end;
708 }
709 }
710
711 if (cc_full_descr->iterator_methods.seek_time) {
712 ret = bt_component_class_filter_set_notification_iterator_seek_time_method(
713 comp_class,
714 cc_full_descr->iterator_methods.seek_time);
715 if (ret) {
3fe0bf43 716 BT_LOGE_STR("Cannot set filter component class's notification iterator seek to time method.");
55bb57e0
PP
717 status = BT_PLUGIN_STATUS_ERROR;
718 BT_PUT(comp_class);
719 goto end;
720 }
721 }
722 break;
723 case BT_COMPONENT_CLASS_TYPE_SINK:
55bb57e0
PP
724 break;
725 default:
0fbb9a9f 726 abort();
55bb57e0
PP
727 }
728
729 /*
730 * Add component class to the plugin object.
731 *
732 * This will call back
733 * bt_plugin_so_on_add_component_class() so that we can
734 * add a mapping in comp_classes_to_shlib_handles when
735 * we know the component class is successfully added.
736 */
737 status = bt_plugin_add_component_class(plugin,
738 comp_class);
739 BT_PUT(comp_class);
740 if (status < 0) {
3fe0bf43 741 BT_LOGE("Cannot add component class to plugin.");
55bb57e0
PP
742 goto end;
743 }
744 }
745
746 /*
747 * All the plugin's component classes should be added at this
748 * point. We freeze the plugin so that it's not possible to add
749 * component classes to this plugin object after this stage
750 * (plugin object becomes immutable).
751 */
752 bt_plugin_freeze(plugin);
753
754end:
755 g_array_free(comp_class_full_descriptors, TRUE);
756 return status;
757}
758
759static
760struct bt_plugin *bt_plugin_so_create_empty(
761 struct bt_plugin_so_shared_lib_handle *shared_lib_handle)
762{
763 struct bt_plugin *plugin;
764 struct bt_plugin_so_spec_data *spec;
765
766 plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_SO);
767 if (!plugin) {
768 goto error;
769 }
770
6fbd4105 771 plugin->destroy_spec_data = bt_plugin_so_destroy_spec_data;
55bb57e0
PP
772 plugin->spec_data = g_new0(struct bt_plugin_so_spec_data, 1);
773 if (!plugin->spec_data) {
3fe0bf43 774 BT_LOGE_STR("Failed to allocate one SO plugin specific data structure.");
55bb57e0
PP
775 goto error;
776 }
777
778 spec = plugin->spec_data;
779 spec->shared_lib_handle = bt_get(shared_lib_handle);
780 goto end;
781
782error:
783 BT_PUT(plugin);
784
785end:
786 return plugin;
787}
788
789static
a8ff38ef 790struct bt_plugin_set *bt_plugin_so_create_all_from_sections(
55bb57e0
PP
791 struct bt_plugin_so_shared_lib_handle *shared_lib_handle,
792 struct __bt_plugin_descriptor const * const *descriptors_begin,
793 struct __bt_plugin_descriptor const * const *descriptors_end,
794 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
795 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
796 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
797 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
798 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
799 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
800{
801 size_t descriptor_count;
802 size_t attrs_count;
803 size_t cc_descriptors_count;
804 size_t cc_descr_attrs_count;
805 size_t i;
a8ff38ef 806 struct bt_plugin_set *plugin_set = NULL;
55bb57e0
PP
807
808 descriptor_count = descriptors_end - descriptors_begin;
809 attrs_count = attrs_end - attrs_begin;
810 cc_descriptors_count = cc_descriptors_end - cc_descriptors_begin;
811 cc_descr_attrs_count = cc_descr_attrs_end - cc_descr_attrs_begin;
3fe0bf43
PP
812
813 BT_LOGD("Creating all SO plugins from sections: "
814 "plugin-path=\"%s\", "
815 "descr-begin-addr=%p, descr-end-addr=%p, "
816 "attrs-begin-addr=%p, attrs-end-addr=%p, "
817 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
818 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p, "
819 "descr-count=%zu, attrs-count=%zu, "
820 "cc-descr-count=%zu, cc-descr-attrs-count=%zu",
821 shared_lib_handle->path ? shared_lib_handle->path->str : NULL,
822 descriptors_begin, descriptors_end,
823 attrs_begin, attrs_end,
824 cc_descriptors_begin, cc_descriptors_end,
825 cc_descr_attrs_begin, cc_descr_attrs_end,
826 descriptor_count, attrs_count,
827 cc_descriptors_count, cc_descr_attrs_count);
a8ff38ef
PP
828 plugin_set = bt_plugin_set_create();
829 if (!plugin_set) {
3fe0bf43 830 BT_LOGE_STR("Cannot create empty plugin set.");
55bb57e0
PP
831 goto error;
832 }
833
834 for (i = 0; i < descriptor_count; i++) {
835 enum bt_plugin_status status;
836 const struct __bt_plugin_descriptor *descriptor =
837 descriptors_begin[i];
838 struct bt_plugin *plugin;
839
3fe0bf43
PP
840 BT_LOGD("Creating plugin object for plugin: "
841 "name=\"%s\", abi-major=%d, abi-minor=%d",
842 descriptor->name, descriptor->major, descriptor->minor);
55bb57e0
PP
843
844 if (descriptor->major > __BT_PLUGIN_VERSION_MAJOR) {
3fe0bf43 845 BT_LOGW("Unknown ABI major version: abi-major=%d",
55bb57e0
PP
846 descriptor->major);
847 goto error;
848 }
849
850 plugin = bt_plugin_so_create_empty(shared_lib_handle);
851 if (!plugin) {
3fe0bf43 852 BT_LOGE_STR("Cannot create empty shared library handle.");
55bb57e0
PP
853 goto error;
854 }
855
856 if (shared_lib_handle && shared_lib_handle->path) {
857 bt_plugin_set_path(plugin, shared_lib_handle->path->str);
858 }
859
860 status = bt_plugin_so_init(plugin, descriptor, attrs_begin,
861 attrs_end, cc_descriptors_begin, cc_descriptors_end,
862 cc_descr_attrs_begin, cc_descr_attrs_end);
863 if (status < 0) {
3fe0bf43 864 BT_LOGW_STR("Cannot initialize SO plugin object from sections.");
55bb57e0
PP
865 BT_PUT(plugin);
866 goto error;
867 }
868
a8ff38ef
PP
869 /* Add to plugin set */
870 bt_plugin_set_add_plugin(plugin_set, plugin);
871 bt_put(plugin);
55bb57e0
PP
872 }
873
874 goto end;
875
876error:
a8ff38ef 877 BT_PUT(plugin_set);
55bb57e0
PP
878
879end:
a8ff38ef 880 return plugin_set;
55bb57e0
PP
881}
882
883BT_HIDDEN
a8ff38ef 884struct bt_plugin_set *bt_plugin_so_create_all_from_static(void)
55bb57e0 885{
a8ff38ef 886 struct bt_plugin_set *plugin_set = NULL;
55bb57e0
PP
887 struct bt_plugin_so_shared_lib_handle *shared_lib_handle =
888 bt_plugin_so_shared_lib_handle_create(NULL);
889
890 if (!shared_lib_handle) {
891 goto end;
892 }
893
3fe0bf43 894 BT_LOGD_STR("Creating all SO plugins from built-in plugins.");
a8ff38ef 895 plugin_set = bt_plugin_so_create_all_from_sections(shared_lib_handle,
55bb57e0
PP
896 SECTION_BEGIN(__bt_plugin_descriptors),
897 SECTION_END(__bt_plugin_descriptors),
898 SECTION_BEGIN(__bt_plugin_descriptor_attributes),
899 SECTION_END(__bt_plugin_descriptor_attributes),
900 SECTION_BEGIN(__bt_plugin_component_class_descriptors),
901 SECTION_END(__bt_plugin_component_class_descriptors),
902 SECTION_BEGIN(__bt_plugin_component_class_descriptor_attributes),
903 SECTION_END(__bt_plugin_component_class_descriptor_attributes));
904
905end:
906 BT_PUT(shared_lib_handle);
907
a8ff38ef 908 return plugin_set;
55bb57e0
PP
909}
910
911BT_HIDDEN
a8ff38ef 912struct bt_plugin_set *bt_plugin_so_create_all_from_file(const char *path)
55bb57e0
PP
913{
914 size_t path_len;
a8ff38ef 915 struct bt_plugin_set *plugin_set = NULL;
55bb57e0
PP
916 struct __bt_plugin_descriptor const * const *descriptors_begin = NULL;
917 struct __bt_plugin_descriptor const * const *descriptors_end = NULL;
918 struct __bt_plugin_descriptor_attribute const * const *attrs_begin = NULL;
919 struct __bt_plugin_descriptor_attribute const * const *attrs_end = NULL;
920 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin = NULL;
921 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end = NULL;
922 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin = NULL;
923 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end = NULL;
c55a9f58 924 bt_bool is_libtool_wrapper = BT_FALSE, is_shared_object = BT_FALSE;
55bb57e0
PP
925 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
926
927 if (!path) {
3fe0bf43 928 BT_LOGW_STR("Invalid parameter: path is NULL.");
55bb57e0
PP
929 goto end;
930 }
931
3fe0bf43 932 BT_LOGD("Creating all SO plugins from file: path=\"%s\"", path);
55bb57e0
PP
933 path_len = strlen(path);
934 if (path_len <= PLUGIN_SUFFIX_LEN) {
3fe0bf43
PP
935 BT_LOGW("Invalid parameter: path length is too short: "
936 "path-length=%zu", path_len);
55bb57e0
PP
937 goto end;
938 }
939
940 path_len++;
941 /*
942 * Check if the file ends with a known plugin file type suffix (i.e. .so
943 * or .la on Linux).
944 */
945 is_libtool_wrapper = !strncmp(LIBTOOL_PLUGIN_SUFFIX,
946 path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN,
947 LIBTOOL_PLUGIN_SUFFIX_LEN);
948 is_shared_object = !strncmp(NATIVE_PLUGIN_SUFFIX,
949 path + path_len - NATIVE_PLUGIN_SUFFIX_LEN,
950 NATIVE_PLUGIN_SUFFIX_LEN);
951 if (!is_shared_object && !is_libtool_wrapper) {
3fe0bf43
PP
952 /* Name indicates this is not a plugin file; not an error */
953 BT_LOGV("File is not a SO plugin file: path=\"%s\"", path);
55bb57e0
PP
954 goto end;
955 }
956
957 shared_lib_handle = bt_plugin_so_shared_lib_handle_create(path);
958 if (!shared_lib_handle) {
3fe0bf43 959 BT_LOGW_STR("Cannot create shared library handle.");
55bb57e0
PP
960 goto end;
961 }
962
963 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_descriptors",
964 (gpointer *) &descriptors_begin)) {
3fe0bf43
PP
965 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
966 "symbol=\"%s\"", path,
967 "__start___bt_plugin_descriptors");
55bb57e0
PP
968 goto end;
969 }
970
971 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_descriptors",
972 (gpointer *) &descriptors_end)) {
3fe0bf43
PP
973 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
974 "symbol=\"%s\"", path,
975 "__stop___bt_plugin_descriptors");
55bb57e0
PP
976 goto end;
977 }
978
979 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_descriptor_attributes",
980 (gpointer *) &attrs_begin)) {
3fe0bf43
PP
981 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
982 "symbol=\"%s\"", path,
983 "__start___bt_plugin_descriptor_attributes");
55bb57e0
PP
984 }
985
986 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_descriptor_attributes",
987 (gpointer *) &attrs_end)) {
3fe0bf43
PP
988 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
989 "symbol=\"%s\"", path,
990 "__stop___bt_plugin_descriptor_attributes");
55bb57e0
PP
991 }
992
993 if ((!!attrs_begin - !!attrs_end) != 0) {
3fe0bf43
PP
994 BT_LOGD("Found section start or end symbol, but not both: "
995 "path=\"%s\", symbol-start=\"%s\", "
996 "symbol-end=\"%s\", symbol-start-addr=%p, "
997 "symbol-end-addr=%p",
998 path, "__start___bt_plugin_descriptor_attributes",
999 "__stop___bt_plugin_descriptor_attributes",
1000 attrs_begin, attrs_end);
55bb57e0
PP
1001 goto end;
1002 }
1003
1004 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_component_class_descriptors",
1005 (gpointer *) &cc_descriptors_begin)) {
3fe0bf43
PP
1006 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1007 "symbol=\"%s\"", path,
1008 "__start___bt_plugin_component_class_descriptors");
55bb57e0
PP
1009 }
1010
1011 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_component_class_descriptors",
1012 (gpointer *) &cc_descriptors_end)) {
3fe0bf43
PP
1013 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1014 "symbol=\"%s\"", path,
1015 "__stop___bt_plugin_component_class_descriptors");
55bb57e0
PP
1016 }
1017
1018 if ((!!cc_descriptors_begin - !!cc_descriptors_end) != 0) {
3fe0bf43
PP
1019 BT_LOGD("Found section start or end symbol, but not both: "
1020 "path=\"%s\", symbol-start=\"%s\", "
1021 "symbol-end=\"%s\", symbol-start-addr=%p, "
1022 "symbol-end-addr=%p",
1023 path, "__start___bt_plugin_component_class_descriptors",
1024 "__stop___bt_plugin_component_class_descriptors",
1025 cc_descriptors_begin, cc_descriptors_end);
55bb57e0
PP
1026 goto end;
1027 }
1028
1029 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_component_class_descriptor_attributes",
1030 (gpointer *) &cc_descr_attrs_begin)) {
3fe0bf43
PP
1031 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1032 "symbol=\"%s\"", path,
1033 "__start___bt_plugin_component_class_descriptor_attributes");
55bb57e0
PP
1034 }
1035
1036 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_component_class_descriptor_attributes",
1037 (gpointer *) &cc_descr_attrs_end)) {
3fe0bf43
PP
1038 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1039 "symbol=\"%s\"", path,
1040 "__stop___bt_plugin_component_class_descriptor_attributes");
55bb57e0
PP
1041 }
1042
1043 if ((!!cc_descr_attrs_begin - !!cc_descr_attrs_end) != 0) {
3fe0bf43
PP
1044 BT_LOGD("Found section start or end symbol, but not both: "
1045 "path=\"%s\", symbol-start=\"%s\", "
1046 "symbol-end=\"%s\", symbol-start-addr=%p, "
1047 "symbol-end-addr=%p",
1048 path, "__start___bt_plugin_component_class_descriptor_attributes",
1049 "__stop___bt_plugin_component_class_descriptor_attributes",
1050 cc_descr_attrs_begin, cc_descr_attrs_end);
55bb57e0
PP
1051 goto end;
1052 }
1053
1054 /* Initialize plugin */
3fe0bf43 1055 BT_LOGD_STR("Initializing plugin object.");
a8ff38ef 1056 plugin_set = bt_plugin_so_create_all_from_sections(shared_lib_handle,
55bb57e0
PP
1057 descriptors_begin, descriptors_end, attrs_begin, attrs_end,
1058 cc_descriptors_begin, cc_descriptors_end,
1059 cc_descr_attrs_begin, cc_descr_attrs_end);
1060
1061end:
1062 BT_PUT(shared_lib_handle);
a8ff38ef 1063 return plugin_set;
55bb57e0
PP
1064}
1065
1066static
1067void plugin_comp_class_destroy_listener(struct bt_component_class *comp_class,
1068 void *data)
1069{
1070 gboolean exists = g_hash_table_remove(comp_classes_to_shlib_handles,
1071 comp_class);
1072 assert(exists);
3fe0bf43
PP
1073 BT_LOGV("Component class destroyed: removed entry from hash table: "
1074 "comp-cls-addr=%p", comp_class);
55bb57e0
PP
1075}
1076
1077BT_HIDDEN
3230ee6b 1078void bt_plugin_so_on_add_component_class(struct bt_plugin *plugin,
55bb57e0
PP
1079 struct bt_component_class *comp_class)
1080{
55bb57e0
PP
1081 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
1082
1083 assert(plugin->spec_data);
1084 assert(plugin->type == BT_PLUGIN_TYPE_SO);
1085
1086 /* Map component class pointer to shared lib handle in global HT */
1087 g_hash_table_insert(comp_classes_to_shlib_handles, comp_class,
1088 bt_get(spec->shared_lib_handle));
1089
1090 /* Add our custom destroy listener */
3230ee6b 1091 bt_component_class_add_destroy_listener(comp_class,
55bb57e0 1092 plugin_comp_class_destroy_listener, NULL);
55bb57e0 1093}
This page took 0.071772 seconds and 4 git commands to generate.