Port: Plugin extension is platform specific
[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
44a3451a 46#define NATIVE_PLUGIN_SUFFIX "." G_MODULE_SUFFIX
55bb57e0
PP
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) {
50ad9320
PP
213 /*
214 * DEBUG-level logging because we're only _trying_ to
215 * open this file as a Babeltrace plugin: if it's not,
216 * it's not an error. And because this can be tried
217 * during bt_plugin_create_all_from_dir(), it's not even
218 * a warning.
219 */
220 BT_LOGD("Cannot open GModule: %s: path=\"%s\"",
3fe0bf43 221 g_module_error(), path);
55bb57e0
PP
222 goto error;
223 }
224
225 goto end;
226
227error:
228 BT_PUT(shared_lib_handle);
229
230end:
3fe0bf43
PP
231 if (shared_lib_handle) {
232 BT_LOGD("Created shared library handle: path=\"%s\", addr=%p",
233 path, shared_lib_handle);
234 }
235
55bb57e0
PP
236 return shared_lib_handle;
237}
238
6fbd4105 239static
55bb57e0
PP
240void bt_plugin_so_destroy_spec_data(struct bt_plugin *plugin)
241{
242 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
243
244 if (!plugin->spec_data) {
245 return;
246 }
247
248 assert(plugin->type == BT_PLUGIN_TYPE_SO);
249 assert(spec);
250 BT_PUT(spec->shared_lib_handle);
251 g_free(plugin->spec_data);
252 plugin->spec_data = NULL;
253}
254
255/*
256 * This function does the following:
257 *
258 * 1. Iterate on the plugin descriptor attributes section and set the
259 * plugin's attributes depending on the attribute types. This
260 * includes the name of the plugin, its description, and its
261 * initialization function, for example.
262 *
263 * 2. Iterate on the component class descriptors section and create one
264 * "full descriptor" (temporary structure) for each one that is found
265 * and attached to our plugin descriptor.
266 *
267 * 3. Iterate on the component class descriptor attributes section and
268 * set the corresponding full descriptor's attributes depending on
269 * the attribute types. This includes the description of the
270 * component class, as well as its initialization and destroy
271 * methods.
272 *
273 * 4. Call the user's plugin initialization function, if any is
274 * defined.
275 *
276 * 5. For each full component class descriptor, create a component class
277 * object, set its optional attributes, and add it to the plugin
278 * object.
279 *
280 * 6. Freeze the plugin object.
281 */
282static
283enum bt_plugin_status bt_plugin_so_init(
284 struct bt_plugin *plugin,
285 const struct __bt_plugin_descriptor *descriptor,
286 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
287 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
288 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
289 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
290 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
291 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
292{
293 /*
294 * This structure's members point to the plugin's memory
295 * (do NOT free).
296 */
297 struct comp_class_full_descriptor {
298 const struct __bt_plugin_component_class_descriptor *descriptor;
299 const char *description;
279b3f15 300 const char *help;
55bb57e0 301 bt_component_class_init_method init_method;
64cadc66 302 bt_component_class_finalize_method finalize_method;
a67681c1 303 bt_component_class_query_method query_method;
72b913fb 304 bt_component_class_accept_port_connection_method accept_port_connection_method;
0d8b4d8e 305 bt_component_class_port_connected_method port_connected_method;
72b913fb 306 bt_component_class_port_disconnected_method port_disconnected_method;
55bb57e0
PP
307 struct bt_component_class_iterator_methods iterator_methods;
308 };
309
310 enum bt_plugin_status status = BT_PLUGIN_STATUS_OK;
311 struct __bt_plugin_descriptor_attribute const * const *cur_attr_ptr;
312 struct __bt_plugin_component_class_descriptor const * const *cur_cc_descr_ptr;
313 struct __bt_plugin_component_class_descriptor_attribute const * const *cur_cc_descr_attr_ptr;
314 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
315 GArray *comp_class_full_descriptors;
316 size_t i;
317 int ret;
318
3fe0bf43
PP
319 BT_LOGD("Initializing plugin object from descriptors found in sections: "
320 "plugin-addr=%p, plugin-path=\"%s\", "
321 "attrs-begin-addr=%p, attrs-end-addr=%p, "
322 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
323 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p",
324 plugin,
325 spec->shared_lib_handle->path ?
326 spec->shared_lib_handle->path->str : NULL,
327 attrs_begin, attrs_end,
328 cc_descriptors_begin, cc_descriptors_end,
329 cc_descr_attrs_begin, cc_descr_attrs_end);
55bb57e0
PP
330 comp_class_full_descriptors = g_array_new(FALSE, TRUE,
331 sizeof(struct comp_class_full_descriptor));
332 if (!comp_class_full_descriptors) {
3fe0bf43 333 BT_LOGE_STR("Failed to allocate a GArray.");
55bb57e0
PP
334 status = BT_PLUGIN_STATUS_ERROR;
335 goto end;
336 }
337
338 /* Set mandatory attributes */
339 spec->descriptor = descriptor;
340 bt_plugin_set_name(plugin, descriptor->name);
341
342 /*
343 * Find and set optional attributes attached to this plugin
344 * descriptor.
345 */
346 for (cur_attr_ptr = attrs_begin; cur_attr_ptr != attrs_end; cur_attr_ptr++) {
347 const struct __bt_plugin_descriptor_attribute *cur_attr =
348 *cur_attr_ptr;
349
350 if (cur_attr->plugin_descriptor != descriptor) {
351 continue;
352 }
353
354 switch (cur_attr->type) {
355 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_INIT:
356 spec->init = cur_attr->value.init;
357 break;
358 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_EXIT:
359 spec->shared_lib_handle->exit = cur_attr->value.exit;
360 break;
361 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_AUTHOR:
362 bt_plugin_set_author(plugin, cur_attr->value.author);
363 break;
364 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_LICENSE:
365 bt_plugin_set_license(plugin, cur_attr->value.license);
366 break;
367 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
368 bt_plugin_set_description(plugin, cur_attr->value.description);
369 break;
370 case BT_PLUGIN_DESCRIPTOR_ATTRIBUTE_TYPE_VERSION:
371 bt_plugin_set_version(plugin,
372 (unsigned int) cur_attr->value.version.major,
373 (unsigned int) cur_attr->value.version.minor,
374 (unsigned int) cur_attr->value.version.patch,
375 cur_attr->value.version.extra);
376 break;
377 default:
50ad9320
PP
378 /*
379 * WARN-level logging because this should not
380 * happen with the appropriate ABI version. If
381 * we're here, we know that for the reported
382 * version of the ABI, this attribute is
383 * unknown.
384 */
3fe0bf43
PP
385 BT_LOGW("Ignoring unknown plugin descriptor attribute: "
386 "plugin-path=\"%s\", plugin-name=\"%s\", "
387 "attr-type-name=\"%s\", attr-type-id=%d",
388 spec->shared_lib_handle->path ?
389 spec->shared_lib_handle->path->str :
390 NULL,
391 descriptor->name, cur_attr->type_name,
392 cur_attr->type);
55bb57e0
PP
393 break;
394 }
395 }
396
397 /*
398 * Find component class descriptors attached to this plugin
399 * descriptor and initialize corresponding full component class
400 * descriptors in the array.
401 */
402 for (cur_cc_descr_ptr = cc_descriptors_begin; cur_cc_descr_ptr != cc_descriptors_end; cur_cc_descr_ptr++) {
403 const struct __bt_plugin_component_class_descriptor *cur_cc_descr =
404 *cur_cc_descr_ptr;
405 struct comp_class_full_descriptor full_descriptor = {0};
406
407 if (cur_cc_descr->plugin_descriptor != descriptor) {
408 continue;
409 }
410
411 full_descriptor.descriptor = cur_cc_descr;
412 g_array_append_val(comp_class_full_descriptors,
413 full_descriptor);
414 }
415
416 /*
417 * Find component class descriptor attributes attached to this
418 * plugin descriptor and update corresponding full component
419 * class descriptors in the array.
420 */
421 for (cur_cc_descr_attr_ptr = cc_descr_attrs_begin; cur_cc_descr_attr_ptr != cc_descr_attrs_end; cur_cc_descr_attr_ptr++) {
422 const struct __bt_plugin_component_class_descriptor_attribute *cur_cc_descr_attr =
423 *cur_cc_descr_attr_ptr;
424
425 if (cur_cc_descr_attr->comp_class_descriptor->plugin_descriptor !=
426 descriptor) {
427 continue;
428 }
429
430 /* Find the corresponding component class descriptor entry */
431 for (i = 0; i < comp_class_full_descriptors->len; i++) {
432 struct comp_class_full_descriptor *cc_full_descr =
433 &g_array_index(comp_class_full_descriptors,
434 struct comp_class_full_descriptor, i);
435
436 if (cur_cc_descr_attr->comp_class_descriptor ==
437 cc_full_descr->descriptor) {
438 switch (cur_cc_descr_attr->type) {
439 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_DESCRIPTION:
440 cc_full_descr->description =
441 cur_cc_descr_attr->value.description;
442 break;
279b3f15
PP
443 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_HELP:
444 cc_full_descr->help =
445 cur_cc_descr_attr->value.help;
446 break;
55bb57e0
PP
447 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_INIT_METHOD:
448 cc_full_descr->init_method =
449 cur_cc_descr_attr->value.init_method;
450 break;
64cadc66
PP
451 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_FINALIZE_METHOD:
452 cc_full_descr->finalize_method =
453 cur_cc_descr_attr->value.finalize_method;
55bb57e0 454 break;
a67681c1
PP
455 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_QUERY_METHOD:
456 cc_full_descr->query_method =
457 cur_cc_descr_attr->value.query_method;
8463eac2 458 break;
72b913fb
PP
459 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_ACCEPT_PORT_CONNECTION_METHOD:
460 cc_full_descr->accept_port_connection_method =
461 cur_cc_descr_attr->value.accept_port_connection_method;
462 break;
0d8b4d8e
PP
463 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_CONNECTED_METHOD:
464 cc_full_descr->port_connected_method =
465 cur_cc_descr_attr->value.port_connected_method;
466 break;
72b913fb
PP
467 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_PORT_DISCONNECTED_METHOD:
468 cc_full_descr->port_disconnected_method =
469 cur_cc_descr_attr->value.port_disconnected_method;
55bb57e0
PP
470 break;
471 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_INIT_METHOD:
472 cc_full_descr->iterator_methods.init =
473 cur_cc_descr_attr->value.notif_iter_init_method;
474 break;
64cadc66
PP
475 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_FINALIZE_METHOD:
476 cc_full_descr->iterator_methods.finalize =
477 cur_cc_descr_attr->value.notif_iter_finalize_method;
55bb57e0
PP
478 break;
479 case BT_PLUGIN_COMPONENT_CLASS_DESCRIPTOR_ATTRIBUTE_TYPE_NOTIF_ITER_SEEK_TIME_METHOD:
480 cc_full_descr->iterator_methods.seek_time =
481 cur_cc_descr_attr->value.notif_iter_seek_time_method;
482 break;
483 default:
50ad9320
PP
484 /*
485 * WARN-level logging because
486 * this should not happen with
487 * the appropriate ABI version.
488 * If we're here, we know that
489 * for the reported version of
490 * the ABI, this attribute is
491 * unknown.
492 */
3fe0bf43
PP
493 BT_LOGW("Ignoring unknown component class descriptor attribute: "
494 "plugin-path=\"%s\", "
495 "plugin-name=\"%s\", "
496 "comp-class-name=\"%s\", "
497 "comp-class-type=%s, "
498 "attr-type-name=\"%s\", "
499 "attr-type-id=%d",
500 spec->shared_lib_handle->path ?
501 spec->shared_lib_handle->path->str :
502 NULL,
503 descriptor->name,
55bb57e0 504 cur_cc_descr_attr->comp_class_descriptor->name,
3fe0bf43
PP
505 bt_component_class_type_string(
506 cur_cc_descr_attr->comp_class_descriptor->type),
507 cur_cc_descr_attr->type_name,
508 cur_cc_descr_attr->type);
55bb57e0
PP
509 break;
510 }
511 }
512 }
513 }
514
515 /* Initialize plugin */
516 if (spec->init) {
3fe0bf43 517 BT_LOGD_STR("Calling user's plugin initialization function.");
55bb57e0 518 status = spec->init(plugin);
3fe0bf43
PP
519 BT_LOGD("User function returned: %s",
520 bt_plugin_status_string(status));
521
55bb57e0 522 if (status < 0) {
3fe0bf43 523 BT_LOGW_STR("User's plugin initialization function failed.");
55bb57e0
PP
524 goto end;
525 }
526 }
527
c55a9f58 528 spec->shared_lib_handle->init_called = BT_TRUE;
55bb57e0
PP
529
530 /* Add described component classes to plugin */
531 for (i = 0; i < comp_class_full_descriptors->len; i++) {
532 struct comp_class_full_descriptor *cc_full_descr =
533 &g_array_index(comp_class_full_descriptors,
534 struct comp_class_full_descriptor, i);
535 struct bt_component_class *comp_class;
536
3fe0bf43
PP
537 BT_LOGD("Creating and setting properties of plugin's component class: "
538 "plugin-path=\"%s\", plugin-name=\"%s\", "
539 "comp-class-name=\"%s\", comp-class-type=%s",
540 spec->shared_lib_handle->path ?
541 spec->shared_lib_handle->path->str :
542 NULL,
543 descriptor->name,
544 cc_full_descr->descriptor->name,
545 bt_component_class_type_string(
546 cc_full_descr->descriptor->type));
547
55bb57e0
PP
548 switch (cc_full_descr->descriptor->type) {
549 case BT_COMPONENT_CLASS_TYPE_SOURCE:
550 comp_class = bt_component_class_source_create(
551 cc_full_descr->descriptor->name,
55bb57e0
PP
552 cc_full_descr->descriptor->methods.source.notif_iter_next);
553 break;
554 case BT_COMPONENT_CLASS_TYPE_FILTER:
555 comp_class = bt_component_class_filter_create(
556 cc_full_descr->descriptor->name,
55bb57e0
PP
557 cc_full_descr->descriptor->methods.source.notif_iter_next);
558 break;
559 case BT_COMPONENT_CLASS_TYPE_SINK:
560 comp_class = bt_component_class_sink_create(
561 cc_full_descr->descriptor->name,
562 cc_full_descr->descriptor->methods.sink.consume);
563 break;
564 default:
50ad9320
PP
565 /*
566 * WARN-level logging because this should not
567 * happen with the appropriate ABI version. If
568 * we're here, we know that for the reported
569 * version of the ABI, this component class type
570 * is unknown.
571 */
3fe0bf43
PP
572 BT_LOGW("Ignoring unknown component class type: "
573 "plugin-path=\"%s\", plugin-name=\"%s\", "
574 "comp-class-name=\"%s\", comp-class-type=%d",
575 spec->shared_lib_handle->path->str ?
576 spec->shared_lib_handle->path->str :
577 NULL,
578 descriptor->name,
55bb57e0 579 cc_full_descr->descriptor->name,
3fe0bf43 580 cc_full_descr->descriptor->type);
55bb57e0
PP
581 continue;
582 }
583
584 if (!comp_class) {
3fe0bf43 585 BT_LOGE_STR("Cannot create component class.");
55bb57e0
PP
586 status = BT_PLUGIN_STATUS_ERROR;
587 goto end;
588 }
589
590 if (cc_full_descr->description) {
591 ret = bt_component_class_set_description(comp_class,
592 cc_full_descr->description);
593 if (ret) {
3fe0bf43 594 BT_LOGE_STR("Cannot set component class's description.");
55bb57e0
PP
595 status = BT_PLUGIN_STATUS_ERROR;
596 BT_PUT(comp_class);
597 goto end;
598 }
599 }
600
279b3f15
PP
601 if (cc_full_descr->help) {
602 ret = bt_component_class_set_help(comp_class,
603 cc_full_descr->help);
604 if (ret) {
3fe0bf43 605 BT_LOGE_STR("Cannot set component class's help string.");
279b3f15
PP
606 status = BT_PLUGIN_STATUS_ERROR;
607 BT_PUT(comp_class);
608 goto end;
609 }
610 }
611
55bb57e0
PP
612 if (cc_full_descr->init_method) {
613 ret = bt_component_class_set_init_method(comp_class,
614 cc_full_descr->init_method);
615 if (ret) {
3fe0bf43 616 BT_LOGE_STR("Cannot set component class's initialization method.");
55bb57e0
PP
617 status = BT_PLUGIN_STATUS_ERROR;
618 BT_PUT(comp_class);
619 goto end;
620 }
621 }
622
64cadc66
PP
623 if (cc_full_descr->finalize_method) {
624 ret = bt_component_class_set_finalize_method(comp_class,
625 cc_full_descr->finalize_method);
55bb57e0 626 if (ret) {
3fe0bf43 627 BT_LOGE_STR("Cannot set component class's finalization method.");
55bb57e0
PP
628 status = BT_PLUGIN_STATUS_ERROR;
629 BT_PUT(comp_class);
630 goto end;
631 }
632 }
633
a67681c1
PP
634 if (cc_full_descr->query_method) {
635 ret = bt_component_class_set_query_method(
636 comp_class, cc_full_descr->query_method);
8463eac2 637 if (ret) {
3fe0bf43 638 BT_LOGE_STR("Cannot set component class's query method.");
8463eac2
PP
639 status = BT_PLUGIN_STATUS_ERROR;
640 BT_PUT(comp_class);
641 goto end;
642 }
643 }
644
72b913fb
PP
645 if (cc_full_descr->accept_port_connection_method) {
646 ret = bt_component_class_set_accept_port_connection_method(
647 comp_class, cc_full_descr->accept_port_connection_method);
648 if (ret) {
3fe0bf43 649 BT_LOGE_STR("Cannot set component class's \"accept port connection\" method.");
72b913fb
PP
650 status = BT_PLUGIN_STATUS_ERROR;
651 BT_PUT(comp_class);
652 goto end;
653 }
654 }
655
0d8b4d8e
PP
656 if (cc_full_descr->port_connected_method) {
657 ret = bt_component_class_set_port_connected_method(
658 comp_class, cc_full_descr->port_connected_method);
659 if (ret) {
3fe0bf43 660 BT_LOGE_STR("Cannot set component class's \"port connected\" method.");
0d8b4d8e
PP
661 status = BT_PLUGIN_STATUS_ERROR;
662 BT_PUT(comp_class);
663 goto end;
664 }
665 }
666
72b913fb
PP
667 if (cc_full_descr->port_disconnected_method) {
668 ret = bt_component_class_set_port_disconnected_method(
669 comp_class, cc_full_descr->port_disconnected_method);
2d41b99e 670 if (ret) {
3fe0bf43 671 BT_LOGE_STR("Cannot set component class's \"port disconnected\" method.");
2d41b99e
JG
672 status = BT_PLUGIN_STATUS_ERROR;
673 BT_PUT(comp_class);
674 goto end;
675 }
676 }
677
55bb57e0
PP
678 switch (cc_full_descr->descriptor->type) {
679 case BT_COMPONENT_CLASS_TYPE_SOURCE:
680 if (cc_full_descr->iterator_methods.init) {
681 ret = bt_component_class_source_set_notification_iterator_init_method(
682 comp_class,
683 cc_full_descr->iterator_methods.init);
684 if (ret) {
3fe0bf43 685 BT_LOGE_STR("Cannot set component class's notification iterator initialization method.");
55bb57e0
PP
686 status = BT_PLUGIN_STATUS_ERROR;
687 BT_PUT(comp_class);
688 goto end;
689 }
690 }
691
64cadc66
PP
692 if (cc_full_descr->iterator_methods.finalize) {
693 ret = bt_component_class_source_set_notification_iterator_finalize_method(
55bb57e0 694 comp_class,
64cadc66 695 cc_full_descr->iterator_methods.finalize);
55bb57e0 696 if (ret) {
3fe0bf43 697 BT_LOGE_STR("Cannot set source component class's notification iterator finalization method.");
55bb57e0
PP
698 status = BT_PLUGIN_STATUS_ERROR;
699 BT_PUT(comp_class);
700 goto end;
701 }
702 }
703
704 if (cc_full_descr->iterator_methods.seek_time) {
705 ret = bt_component_class_source_set_notification_iterator_seek_time_method(
706 comp_class,
707 cc_full_descr->iterator_methods.seek_time);
708 if (ret) {
3fe0bf43 709 BT_LOGE_STR("Cannot set source component class's notification iterator seek to time method.");
55bb57e0
PP
710 status = BT_PLUGIN_STATUS_ERROR;
711 BT_PUT(comp_class);
712 goto end;
713 }
714 }
715 break;
716 case BT_COMPONENT_CLASS_TYPE_FILTER:
55bb57e0
PP
717 if (cc_full_descr->iterator_methods.init) {
718 ret = bt_component_class_filter_set_notification_iterator_init_method(
719 comp_class,
720 cc_full_descr->iterator_methods.init);
721 if (ret) {
3fe0bf43 722 BT_LOGE_STR("Cannot set filter component class's notification iterator initialization method.");
55bb57e0
PP
723 status = BT_PLUGIN_STATUS_ERROR;
724 BT_PUT(comp_class);
725 goto end;
726 }
727 }
728
64cadc66
PP
729 if (cc_full_descr->iterator_methods.finalize) {
730 ret = bt_component_class_filter_set_notification_iterator_finalize_method(
55bb57e0 731 comp_class,
64cadc66 732 cc_full_descr->iterator_methods.finalize);
55bb57e0 733 if (ret) {
3fe0bf43 734 BT_LOGE_STR("Cannot set filter component class's notification iterator finalization method.");
55bb57e0
PP
735 status = BT_PLUGIN_STATUS_ERROR;
736 BT_PUT(comp_class);
737 goto end;
738 }
739 }
740
741 if (cc_full_descr->iterator_methods.seek_time) {
742 ret = bt_component_class_filter_set_notification_iterator_seek_time_method(
743 comp_class,
744 cc_full_descr->iterator_methods.seek_time);
745 if (ret) {
3fe0bf43 746 BT_LOGE_STR("Cannot set filter component class's notification iterator seek to time method.");
55bb57e0
PP
747 status = BT_PLUGIN_STATUS_ERROR;
748 BT_PUT(comp_class);
749 goto end;
750 }
751 }
752 break;
753 case BT_COMPONENT_CLASS_TYPE_SINK:
55bb57e0
PP
754 break;
755 default:
0fbb9a9f 756 abort();
55bb57e0
PP
757 }
758
759 /*
760 * Add component class to the plugin object.
761 *
762 * This will call back
763 * bt_plugin_so_on_add_component_class() so that we can
764 * add a mapping in comp_classes_to_shlib_handles when
765 * we know the component class is successfully added.
766 */
767 status = bt_plugin_add_component_class(plugin,
768 comp_class);
769 BT_PUT(comp_class);
770 if (status < 0) {
3fe0bf43 771 BT_LOGE("Cannot add component class to plugin.");
55bb57e0
PP
772 goto end;
773 }
774 }
775
776 /*
777 * All the plugin's component classes should be added at this
778 * point. We freeze the plugin so that it's not possible to add
779 * component classes to this plugin object after this stage
780 * (plugin object becomes immutable).
781 */
782 bt_plugin_freeze(plugin);
783
784end:
785 g_array_free(comp_class_full_descriptors, TRUE);
786 return status;
787}
788
789static
790struct bt_plugin *bt_plugin_so_create_empty(
791 struct bt_plugin_so_shared_lib_handle *shared_lib_handle)
792{
793 struct bt_plugin *plugin;
794 struct bt_plugin_so_spec_data *spec;
795
796 plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_SO);
797 if (!plugin) {
798 goto error;
799 }
800
6fbd4105 801 plugin->destroy_spec_data = bt_plugin_so_destroy_spec_data;
55bb57e0
PP
802 plugin->spec_data = g_new0(struct bt_plugin_so_spec_data, 1);
803 if (!plugin->spec_data) {
3fe0bf43 804 BT_LOGE_STR("Failed to allocate one SO plugin specific data structure.");
55bb57e0
PP
805 goto error;
806 }
807
808 spec = plugin->spec_data;
809 spec->shared_lib_handle = bt_get(shared_lib_handle);
810 goto end;
811
812error:
813 BT_PUT(plugin);
814
815end:
816 return plugin;
817}
818
819static
a8ff38ef 820struct bt_plugin_set *bt_plugin_so_create_all_from_sections(
55bb57e0
PP
821 struct bt_plugin_so_shared_lib_handle *shared_lib_handle,
822 struct __bt_plugin_descriptor const * const *descriptors_begin,
823 struct __bt_plugin_descriptor const * const *descriptors_end,
824 struct __bt_plugin_descriptor_attribute const * const *attrs_begin,
825 struct __bt_plugin_descriptor_attribute const * const *attrs_end,
826 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin,
827 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end,
828 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin,
829 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end)
830{
831 size_t descriptor_count;
832 size_t attrs_count;
833 size_t cc_descriptors_count;
834 size_t cc_descr_attrs_count;
835 size_t i;
a8ff38ef 836 struct bt_plugin_set *plugin_set = NULL;
55bb57e0
PP
837
838 descriptor_count = descriptors_end - descriptors_begin;
839 attrs_count = attrs_end - attrs_begin;
840 cc_descriptors_count = cc_descriptors_end - cc_descriptors_begin;
841 cc_descr_attrs_count = cc_descr_attrs_end - cc_descr_attrs_begin;
3fe0bf43
PP
842
843 BT_LOGD("Creating all SO plugins from sections: "
844 "plugin-path=\"%s\", "
845 "descr-begin-addr=%p, descr-end-addr=%p, "
846 "attrs-begin-addr=%p, attrs-end-addr=%p, "
847 "cc-descr-begin-addr=%p, cc-descr-end-addr=%p, "
848 "cc-descr-attrs-begin-addr=%p, cc-descr-attrs-end-addr=%p, "
849 "descr-count=%zu, attrs-count=%zu, "
850 "cc-descr-count=%zu, cc-descr-attrs-count=%zu",
851 shared_lib_handle->path ? shared_lib_handle->path->str : NULL,
852 descriptors_begin, descriptors_end,
853 attrs_begin, attrs_end,
854 cc_descriptors_begin, cc_descriptors_end,
855 cc_descr_attrs_begin, cc_descr_attrs_end,
856 descriptor_count, attrs_count,
857 cc_descriptors_count, cc_descr_attrs_count);
a8ff38ef
PP
858 plugin_set = bt_plugin_set_create();
859 if (!plugin_set) {
3fe0bf43 860 BT_LOGE_STR("Cannot create empty plugin set.");
55bb57e0
PP
861 goto error;
862 }
863
864 for (i = 0; i < descriptor_count; i++) {
865 enum bt_plugin_status status;
866 const struct __bt_plugin_descriptor *descriptor =
867 descriptors_begin[i];
868 struct bt_plugin *plugin;
869
3fe0bf43
PP
870 BT_LOGD("Creating plugin object for plugin: "
871 "name=\"%s\", abi-major=%d, abi-minor=%d",
872 descriptor->name, descriptor->major, descriptor->minor);
55bb57e0
PP
873
874 if (descriptor->major > __BT_PLUGIN_VERSION_MAJOR) {
50ad9320
PP
875 /*
876 * DEBUG-level logging because we're only
877 * _trying_ to open this file as a compatible
878 * Babeltrace plugin: if it's not, it's not an
879 * error. And because this can be tried during
880 * bt_plugin_create_all_from_dir(), it's not
881 * even a warning.
882 */
883 BT_LOGD("Unknown ABI major version: abi-major=%d",
55bb57e0
PP
884 descriptor->major);
885 goto error;
886 }
887
888 plugin = bt_plugin_so_create_empty(shared_lib_handle);
889 if (!plugin) {
3fe0bf43 890 BT_LOGE_STR("Cannot create empty shared library handle.");
55bb57e0
PP
891 goto error;
892 }
893
894 if (shared_lib_handle && shared_lib_handle->path) {
895 bt_plugin_set_path(plugin, shared_lib_handle->path->str);
896 }
897
898 status = bt_plugin_so_init(plugin, descriptor, attrs_begin,
899 attrs_end, cc_descriptors_begin, cc_descriptors_end,
900 cc_descr_attrs_begin, cc_descr_attrs_end);
901 if (status < 0) {
50ad9320
PP
902 /*
903 * DEBUG-level logging because we're only
904 * _trying_ to open this file as a compatible
905 * Babeltrace plugin: if it's not, it's not an
906 * error. And because this can be tried during
907 * bt_plugin_create_all_from_dir(), it's not
908 * even a warning.
909 */
910 BT_LOGD_STR("Cannot initialize SO plugin object from sections.");
55bb57e0
PP
911 BT_PUT(plugin);
912 goto error;
913 }
914
a8ff38ef
PP
915 /* Add to plugin set */
916 bt_plugin_set_add_plugin(plugin_set, plugin);
917 bt_put(plugin);
55bb57e0
PP
918 }
919
920 goto end;
921
922error:
a8ff38ef 923 BT_PUT(plugin_set);
55bb57e0
PP
924
925end:
a8ff38ef 926 return plugin_set;
55bb57e0
PP
927}
928
929BT_HIDDEN
a8ff38ef 930struct bt_plugin_set *bt_plugin_so_create_all_from_static(void)
55bb57e0 931{
a8ff38ef 932 struct bt_plugin_set *plugin_set = NULL;
55bb57e0
PP
933 struct bt_plugin_so_shared_lib_handle *shared_lib_handle =
934 bt_plugin_so_shared_lib_handle_create(NULL);
935
936 if (!shared_lib_handle) {
937 goto end;
938 }
939
3fe0bf43 940 BT_LOGD_STR("Creating all SO plugins from built-in plugins.");
a8ff38ef 941 plugin_set = bt_plugin_so_create_all_from_sections(shared_lib_handle,
55bb57e0
PP
942 SECTION_BEGIN(__bt_plugin_descriptors),
943 SECTION_END(__bt_plugin_descriptors),
944 SECTION_BEGIN(__bt_plugin_descriptor_attributes),
945 SECTION_END(__bt_plugin_descriptor_attributes),
946 SECTION_BEGIN(__bt_plugin_component_class_descriptors),
947 SECTION_END(__bt_plugin_component_class_descriptors),
948 SECTION_BEGIN(__bt_plugin_component_class_descriptor_attributes),
949 SECTION_END(__bt_plugin_component_class_descriptor_attributes));
950
951end:
952 BT_PUT(shared_lib_handle);
953
a8ff38ef 954 return plugin_set;
55bb57e0
PP
955}
956
957BT_HIDDEN
a8ff38ef 958struct bt_plugin_set *bt_plugin_so_create_all_from_file(const char *path)
55bb57e0
PP
959{
960 size_t path_len;
a8ff38ef 961 struct bt_plugin_set *plugin_set = NULL;
55bb57e0
PP
962 struct __bt_plugin_descriptor const * const *descriptors_begin = NULL;
963 struct __bt_plugin_descriptor const * const *descriptors_end = NULL;
964 struct __bt_plugin_descriptor_attribute const * const *attrs_begin = NULL;
965 struct __bt_plugin_descriptor_attribute const * const *attrs_end = NULL;
966 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_begin = NULL;
967 struct __bt_plugin_component_class_descriptor const * const *cc_descriptors_end = NULL;
968 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_begin = NULL;
969 struct __bt_plugin_component_class_descriptor_attribute const * const *cc_descr_attrs_end = NULL;
c55a9f58 970 bt_bool is_libtool_wrapper = BT_FALSE, is_shared_object = BT_FALSE;
55bb57e0
PP
971 struct bt_plugin_so_shared_lib_handle *shared_lib_handle = NULL;
972
973 if (!path) {
3fe0bf43 974 BT_LOGW_STR("Invalid parameter: path is NULL.");
55bb57e0
PP
975 goto end;
976 }
977
3fe0bf43 978 BT_LOGD("Creating all SO plugins from file: path=\"%s\"", path);
55bb57e0
PP
979 path_len = strlen(path);
980 if (path_len <= PLUGIN_SUFFIX_LEN) {
3fe0bf43
PP
981 BT_LOGW("Invalid parameter: path length is too short: "
982 "path-length=%zu", path_len);
55bb57e0
PP
983 goto end;
984 }
985
986 path_len++;
987 /*
988 * Check if the file ends with a known plugin file type suffix (i.e. .so
989 * or .la on Linux).
990 */
991 is_libtool_wrapper = !strncmp(LIBTOOL_PLUGIN_SUFFIX,
992 path + path_len - LIBTOOL_PLUGIN_SUFFIX_LEN,
993 LIBTOOL_PLUGIN_SUFFIX_LEN);
994 is_shared_object = !strncmp(NATIVE_PLUGIN_SUFFIX,
995 path + path_len - NATIVE_PLUGIN_SUFFIX_LEN,
996 NATIVE_PLUGIN_SUFFIX_LEN);
997 if (!is_shared_object && !is_libtool_wrapper) {
3fe0bf43
PP
998 /* Name indicates this is not a plugin file; not an error */
999 BT_LOGV("File is not a SO plugin file: path=\"%s\"", path);
55bb57e0
PP
1000 goto end;
1001 }
1002
1003 shared_lib_handle = bt_plugin_so_shared_lib_handle_create(path);
1004 if (!shared_lib_handle) {
50ad9320 1005 BT_LOGD_STR("Cannot create shared library handle.");
55bb57e0
PP
1006 goto end;
1007 }
1008
1009 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_descriptors",
1010 (gpointer *) &descriptors_begin)) {
3fe0bf43
PP
1011 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1012 "symbol=\"%s\"", path,
1013 "__start___bt_plugin_descriptors");
55bb57e0
PP
1014 goto end;
1015 }
1016
1017 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_descriptors",
1018 (gpointer *) &descriptors_end)) {
3fe0bf43
PP
1019 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1020 "symbol=\"%s\"", path,
1021 "__stop___bt_plugin_descriptors");
55bb57e0
PP
1022 goto end;
1023 }
1024
1025 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_descriptor_attributes",
1026 (gpointer *) &attrs_begin)) {
3fe0bf43
PP
1027 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1028 "symbol=\"%s\"", path,
1029 "__start___bt_plugin_descriptor_attributes");
55bb57e0
PP
1030 }
1031
1032 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_descriptor_attributes",
1033 (gpointer *) &attrs_end)) {
3fe0bf43
PP
1034 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1035 "symbol=\"%s\"", path,
1036 "__stop___bt_plugin_descriptor_attributes");
55bb57e0
PP
1037 }
1038
1039 if ((!!attrs_begin - !!attrs_end) != 0) {
3fe0bf43
PP
1040 BT_LOGD("Found section start or end symbol, but not both: "
1041 "path=\"%s\", symbol-start=\"%s\", "
1042 "symbol-end=\"%s\", symbol-start-addr=%p, "
1043 "symbol-end-addr=%p",
1044 path, "__start___bt_plugin_descriptor_attributes",
1045 "__stop___bt_plugin_descriptor_attributes",
1046 attrs_begin, attrs_end);
55bb57e0
PP
1047 goto end;
1048 }
1049
1050 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_component_class_descriptors",
1051 (gpointer *) &cc_descriptors_begin)) {
3fe0bf43
PP
1052 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1053 "symbol=\"%s\"", path,
1054 "__start___bt_plugin_component_class_descriptors");
55bb57e0
PP
1055 }
1056
1057 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_component_class_descriptors",
1058 (gpointer *) &cc_descriptors_end)) {
3fe0bf43
PP
1059 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1060 "symbol=\"%s\"", path,
1061 "__stop___bt_plugin_component_class_descriptors");
55bb57e0
PP
1062 }
1063
1064 if ((!!cc_descriptors_begin - !!cc_descriptors_end) != 0) {
3fe0bf43
PP
1065 BT_LOGD("Found section start or end symbol, but not both: "
1066 "path=\"%s\", symbol-start=\"%s\", "
1067 "symbol-end=\"%s\", symbol-start-addr=%p, "
1068 "symbol-end-addr=%p",
1069 path, "__start___bt_plugin_component_class_descriptors",
1070 "__stop___bt_plugin_component_class_descriptors",
1071 cc_descriptors_begin, cc_descriptors_end);
55bb57e0
PP
1072 goto end;
1073 }
1074
1075 if (!g_module_symbol(shared_lib_handle->module, "__start___bt_plugin_component_class_descriptor_attributes",
1076 (gpointer *) &cc_descr_attrs_begin)) {
3fe0bf43
PP
1077 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1078 "symbol=\"%s\"", path,
1079 "__start___bt_plugin_component_class_descriptor_attributes");
55bb57e0
PP
1080 }
1081
1082 if (!g_module_symbol(shared_lib_handle->module, "__stop___bt_plugin_component_class_descriptor_attributes",
1083 (gpointer *) &cc_descr_attrs_end)) {
3fe0bf43
PP
1084 BT_LOGD("Cannot resolve plugin symbol: path=\"%s\", "
1085 "symbol=\"%s\"", path,
1086 "__stop___bt_plugin_component_class_descriptor_attributes");
55bb57e0
PP
1087 }
1088
1089 if ((!!cc_descr_attrs_begin - !!cc_descr_attrs_end) != 0) {
3fe0bf43
PP
1090 BT_LOGD("Found section start or end symbol, but not both: "
1091 "path=\"%s\", symbol-start=\"%s\", "
1092 "symbol-end=\"%s\", symbol-start-addr=%p, "
1093 "symbol-end-addr=%p",
1094 path, "__start___bt_plugin_component_class_descriptor_attributes",
1095 "__stop___bt_plugin_component_class_descriptor_attributes",
1096 cc_descr_attrs_begin, cc_descr_attrs_end);
55bb57e0
PP
1097 goto end;
1098 }
1099
1100 /* Initialize plugin */
3fe0bf43 1101 BT_LOGD_STR("Initializing plugin object.");
a8ff38ef 1102 plugin_set = bt_plugin_so_create_all_from_sections(shared_lib_handle,
55bb57e0
PP
1103 descriptors_begin, descriptors_end, attrs_begin, attrs_end,
1104 cc_descriptors_begin, cc_descriptors_end,
1105 cc_descr_attrs_begin, cc_descr_attrs_end);
1106
1107end:
1108 BT_PUT(shared_lib_handle);
a8ff38ef 1109 return plugin_set;
55bb57e0
PP
1110}
1111
1112static
1113void plugin_comp_class_destroy_listener(struct bt_component_class *comp_class,
1114 void *data)
1115{
1116 gboolean exists = g_hash_table_remove(comp_classes_to_shlib_handles,
1117 comp_class);
1118 assert(exists);
3fe0bf43
PP
1119 BT_LOGV("Component class destroyed: removed entry from hash table: "
1120 "comp-cls-addr=%p", comp_class);
55bb57e0
PP
1121}
1122
1123BT_HIDDEN
3230ee6b 1124void bt_plugin_so_on_add_component_class(struct bt_plugin *plugin,
55bb57e0
PP
1125 struct bt_component_class *comp_class)
1126{
55bb57e0
PP
1127 struct bt_plugin_so_spec_data *spec = plugin->spec_data;
1128
1129 assert(plugin->spec_data);
1130 assert(plugin->type == BT_PLUGIN_TYPE_SO);
1131
1132 /* Map component class pointer to shared lib handle in global HT */
1133 g_hash_table_insert(comp_classes_to_shlib_handles, comp_class,
1134 bt_get(spec->shared_lib_handle));
1135
1136 /* Add our custom destroy listener */
3230ee6b 1137 bt_component_class_add_destroy_listener(comp_class,
55bb57e0 1138 plugin_comp_class_destroy_listener, NULL);
55bb57e0 1139}
This page took 0.075758 seconds and 4 git commands to generate.